我使用以下代码创建(并频繁更新(用户索引(此处为演示目的而缩短了一点(:
Lucene.Net.Store.Directory directory = FSDirectory.Open(new System.IO.DirectoryInfo("TestLuceneIndex"));
StandardAnalyzer standardAnalyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
IndexWriter indexWriter = new IndexWriter(directory, standardAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED);
Document doc = new Document();
doc.Add(new Field("UID", uid, Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
doc.Add(new Field("GENDER", gender, Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
doc.Add(new Field("COUNTRY", countrycode, Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
doc.Add(new Field("CITY", citycode, Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
doc.Add(new Field("USERDATA", userdata, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
doc.Add(new Field("USERINFO", userinfo, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
indexWriter.UpdateDocument(new Term("UID", uid), doc);
indexWriter.Optimize();
indexWriter.Commit();
indexWriter.Close();
存储在索引中的值如下:
UID-用户id(字符串GUID(GENDER-性别id(字符串"0"(未识别("1"(男性(或"2"(女性(国家/地区代码(字符串如"US"、"FR"等(CITY-城市代码(字符串"A121"、"C432"等(USERDATA-用户详细信息的长字符串(类似于"John Doej.doe@gmail.com设计师高等教育5年经验"(USERINFO-关于用户的长字符串(类似于"我的名字是John Doe。我出生了…"(
然后我在索引中执行搜索。我在两个字段(USERDATA和USERINFO(中进行搜索,必要时我会按性别、国家和城市过滤结果。因此,我检索UID(我需要这个值来标识DB中用户记录的id(。
这是我用来搜索的代码:
Lucene.Net.Store.Directory directory = Lucene.Net.Store.FSDirectory.Open(new System.IO.DirectoryInfo("TestLuceneIndex");
standardAnalyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
Lucene.Net.Index.IndexReader indexReader = Lucene.Net.Index.IndexReader.Open(directory, true);
indexSearcher = new Lucene.Net.Search.IndexSearcher(indexReader);
Lucene.Net.Search.BooleanQuery booleanQuery = new Lucene.Net.Search.BooleanQuery();
Lucene.Net.QueryParsers.MultiFieldQueryParser queryTextParser = new Lucene.Net.QueryParsers.MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_29, new string[] { "USERDATA", "USERINFO" }, standardAnalyzer);
Lucene.Net.Search.Query queryText = queryTextParser.Parse(SearchText);
booleanQuery.Add(queryText, Lucene.Net.Search.BooleanClause.Occur.MUST);
if (searchGender != "0")
{
Lucene.Net.Index.Term termGender = new Lucene.Net.Index.Term("GENDER", searchGender);
Lucene.Net.Search.Query queryGender = new Lucene.Net.Search.TermQuery(termGender);
booleanQuery.Add(queryGender, Lucene.Net.Search.BooleanClause.Occur.MUST);
}
if (searchCity != "0")
{
Lucene.Net.Index.Term termCity = new Lucene.Net.Index.Term("CITY", searchCity);
Lucene.Net.Search.Query queryCity = new Lucene.Net.Search.TermQuery(termCity);
booleanQuery.Add(queryCity, Lucene.Net.Search.BooleanClause.Occur.MUST);
}
if (searchCountry != "0")
{
Lucene.Net.Index.Term termCountry = new Lucene.Net.Index.Term("COUNTRY", searchCountry);
Lucene.Net.Search.Query queryCountry = new Lucene.Net.Search.TermQuery(termCountry);
booleanQuery.Add(queryCountry, Lucene.Net.Search.BooleanClause.Occur.MUST);
}
Lucene.Net.Search.TopScoreDocCollector collector = Lucene.Net.Search.TopScoreDocCollector.create(indexReader.MaxDoc(), true);
indexSearcher.Search(booleanQuery, collector);
Lucene.Net.Search.ScoreDoc[] scoreDocs=collector.TopDocs().scoreDocs;
Lucene.Net.Highlight.Formatter formatter = new Lucene.Net.Highlight.SimpleHTMLFormatter("<b>", "</b>");
Lucene.Net.Highlight.QueryScorer queryScorer = new Lucene.Net.Highlight.QueryScorer(booleanQuery);
highlighter = new Lucene.Net.Highlight.Highlighter(formatter, queryScorer);
Lucene.Net.Highlight.Fragmenter fragmenter = new Lucene.Net.Highlight.SimpleFragmenter(150);
highlighter.SetTextFragmenter(fragmenter);
除了使用几个词时的相关性之外,其他一切都很好:例如,当我搜索(microsoft.net程序员(时,包含精确子字符串的结果不会比在文本的不同位置包含这些单词的结果得分更高。据我所知,这是因为分数计算是基于文本中搜索字符串的百分比因素,而不是字符串重合度的精确性。但如何迫使评分算法对资产的准确性更有价值呢?也就是说,在相关性计算中,如何强迫被认为更重要的单词之间的距离?
-
最有效(也是最耗费人力的方法(的方法是编写自己的查询对象,这将提高对单词非常接近的文档的相关性。SpanQuery将是一个很好的起点。
-
最简单的方法是使用邻近搜索和常规布尔查询:
("search text"~10 || (search && text))
。这将使邻近短语匹配度更高。
4.3.邻近搜索-Lucene支持查找特定距离内的单词。要进行邻近搜索,请使用波浪号"~",短语末尾的符号。例如,搜索"apache"one_answers"jakarta"在一份文件中彼此相距10个字以内使用搜索:"jakarta apache"~10
由于您正在构建自己的查询,您甚至可以将"search text"~10
提升到高于(search && text)
的"search text"~20
。