Lucene.Net:单词之间距离的相关性

时间:2011-07-07 11:31:32

标签: lucene.net relevance

我使用以下代码创建(并经常更新)用户索引(为了演示目的,有点缩短):

            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) 性别 - 性别的ID(字符串“0”(未识别)“1”(男性)或“2”(女性) 国家/地区代码(字符串如“US”,“FR”等) CITY - 城市代码(字符串“A121”,“C432”等) USERDATA - 长串用户详细信息(类似“John Doe j.doe@gmail.com设计师高等教育5年经验”) USERINFO - 关于用户的长串文本(类似“我的名字是John Doe。我出生了......”)

然后我在索引中执行搜索。我在两个字段(USERDATA和USERINFO)中搜索,只要有必要,我会按GENDER,COUNTRY和CITY过滤结果。结果我检索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程序员)的实例时,包含精确子字符串的结果的得分不会高于包含不同文本位置的那些单词的结果。据我所知,这是由简单的事实引起的,即分数计算是基于文本中搜索字符串的百分比因子,而不是字符串重合的准确性。但是如何强制评分算法对资产的准确性更有价值?即如何强制在计算相关性时被认为更重要的单词之间的距离?

1 个答案:

答案 0 :(得分:2)

  1. 最有效(也是最耗费人力的方式)就是编写自己的查询对象,这样可以提高与文本紧密相关的文档的更高相关性。 SpanQuery将是一个很好的起点。

  2. 最简单的方法是使用邻近搜索和常规布尔查询:("search text"~10 || (search && text))。这将使邻近短语匹配更高。

  3.   

    4.3。 Proximity Searches -   Lucene支持在特定距离内找到单词。要进行邻近搜索,请使用代字号“〜”,   短语结尾处的符号。例如,搜索“apache”   与文件中的“雅加达”在10个字之内使用   搜索:“jakarta apache”~10

    由于您要构建自己的查询,因此甚至可以提升"search text"~10以上"search text"~20,其提升幅度高于(search && text)