Changeset 915 for trunk/CrypCore


Ignore:
Timestamp:
Nov 29, 2009, 4:14:16 PM (12 years ago)
Author:
enkler
Message:

Added FuzzySearch to SearchProvider

Location:
trunk/CrypCore
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/CrypCore/CrypCore.csproj

    r883 r915  
    5656    <Compile Include="EventArgs.cs" />
    5757    <Compile Include="Exceptions.cs" />
     58    <Compile Include="FuzzySearch.cs" />
    5859    <Compile Include="PluginManager.cs" />
    5960    <Compile Include="Properties\AssemblyInfo.cs" />
  • trunk/CrypCore/SearchProvider.cs

    r887 r915  
    109109        private const int ContextLeftOffset = 15;
    110110        private const int ContextRightOffset = 35;
     111        private const float MinSimilarity = 0.7f;
    111112
    112113        public override void Search(string SearchString)
     
    117118            var searcher = new IndexSearcher(dir);
    118119            var parser = new QueryParser(ContentField, new StandardAnalyzer());
    119             Query query = parser.Parse(SearchString);
    120120
    121             Hits hits = searcher.Search(query);
     121            foreach (var s in SearchString.Split(new []{' '}))
     122            {
     123                var query = parser.GetFuzzyQuery(ContentField, s, MinSimilarity);
    122124
    123             for (int i = 0; i < hits.Length(); i++)
    124             {
    125                 Document doc = hits.Doc(i);
    126                 var result = new SearchResult { Score = hits.Score(i), Plugin = doc.Get(PluginField) };
     125                Hits hits = searcher.Search(query);
    127126
    128                 //Text des aktuellen Dokuments auslesen
    129                 string text = doc.Get(ContentField);
    130                 //Alle indizierten Wörter dieses Dokumentes auslesen
    131                 var tpv = (TermPositionVector)IndexReader.Open(dir).GetTermFreqVector(hits.Id(i), ContentField);
    132                 String[] DocTerms = tpv.GetTerms();
    133                 //Die Anzahl der Erscheinungen aller Wörter auslesen
    134                 int[] freq = tpv.GetTermFrequencies();
    135                 //Hier wollen wir nun die Positionen der Erscheinungen des Suchwortes herausfinden
    136                 for (int t = 0; t < freq.Length; t++)
     127                for (int i = 0; i < hits.Length(); i++)
    137128                {
    138                     //Falls das Suchwort mit dem aktuellen Wort übereinstimmt...
    139                     if (DocTerms[t].Equals(SearchString))
     129                    Document doc = hits.Doc(i);
     130                    var result = new SearchResult { Score = hits.Score(i), Plugin = doc.Get(PluginField) };
     131
     132                    //Text des aktuellen Dokuments auslesen
     133                    string text = doc.Get(ContentField);
     134                    //Alle indizierten Wörter dieses Dokumentes auslesen
     135                    var tpv = (TermPositionVector)IndexReader.Open(dir).GetTermFreqVector(hits.Id(i), ContentField);
     136                    String[] DocTerms = tpv.GetTerms();
     137                    //Die Anzahl der Erscheinungen aller Wörter auslesen
     138                    int[] freq = tpv.GetTermFrequencies();
     139                    var words = new List<string>(DocTerms);
     140                    //Hier wollen wir nun die Positionen der Erscheinungen des Suchwortes herausfinden
     141                    for (int t = 0; t < freq.Length; t++)
    140142                    {
    141                         //...können wir die Positionen auslesen
    142                         TermVectorOffsetInfo[] offsets = tpv.GetOffsets(t);
    143                         //Das Array beinhaltet nun für das Suchwort alle Auftreten mit jeweils Anfang und Ende
    144                         for (int j = 0; j < offsets.Length; j++)
     143                        //Falls das Suchwort mit dem aktuellen Wort übereinstimmt...
     144                        if (ContainsSearchString(SearchString, DocTerms[t], words))
    145145                        {
    146                             //Jetz muss nur noch ein kleiner Kontextausschnitt ausgelesen werden, damit der User etwas damit anfangen kann
    147                             int start = offsets[j].GetStartOffset();
    148                             int end = offsets[j].GetEndOffset();
    149                             int contextStart = start - ContextLeftOffset;
    150                             contextStart = contextStart < 0 ? 0 : contextStart;
    151                             int contextEnd = end + ContextRightOffset;
    152                             contextEnd = contextEnd > text.Length ? text.Length : contextEnd;
    153                             //Nun wollen wir noch bis zum Ende des nächsten Wortes lesen, um das Ergebnis besser lesbar zu machen
    154                             int nextEndSpace = text.IndexOf(" ", contextEnd);
    155                             contextEnd = nextEndSpace > 0 ? nextEndSpace : contextEnd;
    156                             //Maximal so viele Zeichen darf der Text nach einem Leerzeichen links von dem Suchergebnis durchsucht werden
    157                             int leftSpaceOffset = contextStart;
    158                             //Finden des nächstenLeerzeichens links vom Suchergebnis
    159                             int nextStartSpace = text.LastIndexOf(" ", contextStart, leftSpaceOffset);
    160                             //Falls es kein Space in der Nöhe gibt brauchen wir natürlich auch nichts verändern
    161                             contextStart = nextStartSpace > 0 ? nextStartSpace : contextStart;
    162                             int contextLength = contextEnd - contextStart;
    163                             contextLength = contextLength > text.Length ? text.Length : contextLength;
    164                             //Kontext auslesen
    165                             string context = text.Substring(contextStart, contextLength);
    166                             //und den Searchresults zusammen mit dem zugehörigen PlugInNamen und dem HitScore hinzufügen
    167                             result.Contexts.Add(context);
     146                            //...können wir die Positionen auslesen
     147                            TermVectorOffsetInfo[] offsets = tpv.GetOffsets(t);
     148                            //Das Array beinhaltet nun für das Suchwort alle Auftreten mit jeweils Anfang und Ende
     149                            for (int j = 0; j < offsets.Length; j++)
     150                            {
     151                                //Jetz muss nur noch ein kleiner Kontextausschnitt ausgelesen werden, damit der User etwas damit anfangen kann
     152                                int start = offsets[j].GetStartOffset();
     153                                int end = offsets[j].GetEndOffset();
     154                                int contextStart = start - ContextLeftOffset;
     155                                contextStart = contextStart < 0 ? 0 : contextStart;
     156                                int contextEnd = end + ContextRightOffset;
     157                                contextEnd = contextEnd > text.Length ? text.Length : contextEnd;
     158                                //Nun wollen wir noch bis zum Ende des nächsten Wortes lesen, um das Ergebnis besser lesbar zu machen
     159                                int nextEndSpace = text.IndexOf(" ", contextEnd);
     160                                contextEnd = nextEndSpace > 0 ? nextEndSpace : contextEnd;
     161                                //Maximal so viele Zeichen darf der Text nach einem Leerzeichen links von dem Suchergebnis durchsucht werden
     162                                int leftSpaceOffset = contextStart;
     163                                //Finden des nächstenLeerzeichens links vom Suchergebnis
     164                                int nextStartSpace = text.LastIndexOf(" ", contextStart, leftSpaceOffset);
     165                                //Falls es kein Space in der Nöhe gibt brauchen wir natürlich auch nichts verändern
     166                                contextStart = nextStartSpace > 0 ? nextStartSpace : contextStart;
     167                                int contextLength = contextEnd - contextStart;
     168                                contextLength = contextLength > text.Length ? text.Length : contextLength;
     169                                //Kontext auslesen
     170                                string context = text.Substring(contextStart, contextLength);
     171                                //und den Searchresults zusammen mit dem zugehörigen PlugInNamen und dem HitScore hinzufügen
     172                                result.Contexts.Add(context);
     173                            }
    168174                        }
    169175                    }
     176                    SearchResults.Add(result);
    170177                }
    171                 SearchResults.Add(result);
    172178            }
     179        }
     180
     181        private static bool ContainsSearchString(string searchString, string docTerm, List<string> words)
     182        {
     183            var searchStrings = searchString.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
     184            foreach (var s in searchStrings)
     185            {
     186                var fuzzyWords = new HashSet<string>(FuzzySearch.Search(s, words, MinSimilarity));
     187                if (fuzzyWords.Contains(docTerm))
     188                    return true;
     189            }
     190
     191            return false;
    173192        }
    174193    }
Note: See TracChangeset for help on using the changeset viewer.