Lucene.NET Search Results

I use this code to index:

public void IndexEmployees(IEnumerable<Employee> employees) { var indexPath = GetIndexPath(); var directory = FSDirectory.Open(indexPath); var indexWriter = new IndexWriter(directory, new StandardAnalyzer(Version.LUCENE_29), true, IndexWriter.MaxFieldLength.UNLIMITED); foreach (var employee in employees) { var document = new Document(); document.Add(new Field("EmployeeId", employee.EmployeeId.ToString(), Field.Store.YES, Field.Index.NO, Field.TermVector.NO)); document.Add(new Field("Name", employee.FirstName + " " + employee.LastName, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO)); document.Add(new Field("OfficeName", employee.OfficeName, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO)); document.Add(new Field("CompetenceRatings", string.Join(" ", employee.CompetenceRatings.Select(cr => cr.Name)), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO)); indexWriter.AddDocument(document); } indexWriter.Optimize(); indexWriter.Close(); var indexReader = IndexReader.Open(directory, true); var spell = new SpellChecker.Net.Search.Spell.SpellChecker(directory); spell.ClearIndex(); spell.IndexDictionary(new LuceneDictionary(indexReader, "Name")); spell.IndexDictionary(new LuceneDictionary(indexReader, "OfficeName")); spell.IndexDictionary(new LuceneDictionary(indexReader, "CompetenceRatings")); } public DirectoryInfo GetIndexPath() { return new DirectoryInfo(HttpContext.Current.Server.MapPath("/App_Data/EmployeeIndex/")); } 

And this code to find results (as well as suggestions):

 public SearchResult Search(DirectoryInfo indexPath, string[] searchFields, string searchQuery) { var directory = FSDirectory.Open(indexPath); var standardAnalyzer = new StandardAnalyzer(Version.LUCENE_29); var indexReader = IndexReader.Open(directory, true); var indexSearcher = new IndexSearcher(indexReader); var parser = new MultiFieldQueryParser(Version.LUCENE_29, searchFields, standardAnalyzer); //parser.SetDefaultOperator(QueryParser.Operator.OR); var query = parser.Parse(searchQuery); var hits = indexSearcher.Search(query, null, 5000); return new SearchResult { Suggestions = FindSuggestions(indexPath, searchQuery), LuceneDocuments = hits .scoreDocs .Select(scoreDoc => indexSearcher.Doc(scoreDoc.doc)) .ToArray() }; } public string[] FindSuggestions(DirectoryInfo indexPath, string searchQuery) { var directory = FSDirectory.Open(indexPath); var spell = new SpellChecker.Net.Search.Spell.SpellChecker(directory); var similarWords = spell.SuggestSimilar(searchQuery, 20); return similarWords; } var searchResult = Search(GetIndexPath(), new[] { "Name", "OfficeName", "CompetenceRatings" }, "admin*"); 

Simple queries, such as: admin or admin *, do not give me any results. I know that there is an employee with that name. I want to find James Jameson if I look for James.

Thanks!

+4
source share
3 answers

The first one. You must commit changes to the index.

 indexWriter.Optimize(); indexWriter.Commit(); //Add This indexWriter.Close(); 

Edit # 2 Also, keep it simple until you get something that works.

Comment on this.

 //var indexReader = IndexReader.Open(directory, true); //var spell = new SpellChecker.Net.Search.Spell.SpellChecker(directory); //spell.ClearIndex(); //spell.IndexDictionary(new LuceneDictionary(indexReader, "Name")); //spell.IndexDictionary(new LuceneDictionary(indexReader, "OfficeName")); //spell.IndexDictionary(new LuceneDictionary(indexReader, "CompetenceRatings")); 

Edit # 3

The fields you are looking for will probably not change frequently. I would include them in your search function.

 string[] fields = new string[] { "Name", "OfficeName", "CompetenceRatings" }; 

The biggest reason I propose this is because the fields are case sensitive and sometimes you wonโ€™t get any results because you are looking for the name field (which does not exist) instead of the Name field. It is easier to detect the error in this way.

+4
source

In my (limited) experience with Lucene, I found that you need to create your own query in order to get the google behavior. Here is what I do, YMMV, but it generates the expected results in my application. The basic idea is that you combine the term query (exact match), the prefix query (everything that starts with the term), and the fuzzy query for each term in the search bar. The code below will not compile, but gives you an idea

 Query GetQuery(string querystring) { Search.Search.BooleanQuery query = new Search.Search.BooleanQuery(); Search.Analysis.TokenStream tk = StandardAnalyzerInstance.TokenStream(null, new StringReader(querystring)); Search.Analysis.Tokenattributes.TermAttribute ta = tk.GetAttribute(typeof(Search.Analysis.Tokenattributes.TermAttribute)) as Search.Analysis.Tokenattributes.TermAttribute; while (tk.IncrementToken()) { string term = ta.Term(); Search.Search.BooleanQuery bq = new Search.Search.BooleanQuery(); bq.Add(new Search.Search.TermQuery(new Search.Index.Term("fieldToQuery", term)), Search.Search.BooleanClause.Occur.SHOULD); bq.Add(new Search.Search.PrefixQuery(new Search.Index.Term("fieldToQuery", term)), Search.Search.BooleanClause.Occur.SHOULD); bq.Add(new Search.Search.FuzzyQuery(new Search.Index.Term("fieldToQuery", term)), Search.Search.BooleanClause.Occur.SHOULD); query.Add(bq, Search.Search.BooleanClause.Occur.MUST); } return query; } 
+1
source

This Parse () method is inherited. Have you tried using static methods that return a Query object?

 Parse(Version matchVersion, String[] queries, String[] fields, Analyzer analyzer) 
0
source

Source: https://habr.com/ru/post/1392961/


All Articles