【问题标题】:How to Store Boost Factor of Field in Index in lucene如何在lucene中存储索引中的字段增强因子
【发布时间】:2011-11-10 09:08:59
【问题描述】:

我正在使用 lucene 在通讯录中搜索产品。我想根据一些特定的标准来提升搜索结果。 (例如,位置字段中的匹配应该比实体名称中的匹配具有更大的相关性。)这是我的案例的固定标准。

我正在尝试通过在索引时调用 SetBoost() 方法将 boostfactor 与 Field 一起存储。但是结果的分数也不如预期。它为每个字段考虑相同的提升值。

谁能建议我哪里出错了?

我用来构建索引的代码。

Directory objIndexDirectory =
  FSDirectory.Open(new System.IO.DirectoryInfo(<PathOfIndexFolder>));
StandardAnalyzer objAnalyzer =
  new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
IndexWriter objWriter = new IndexWriter(
  objIndexDirectory, objAnalyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);
Document objDocument = new Document();
Field objName =
  new Field("Name", "John Doe", Field.Store.YES, Field.Index.ANALYZED);
Field objLocation =
  new Field("Location", "NY", Field.Store.YES, Field.Index.NOT_ANALYZED);
objLocation.SetBoost((2f);
objDocument.Add(objName);
objDocument.Add(objLocation);
objWriter.AddDocument(objDocument);

我想要实现的是, 假设索引中有三个条目:

  1. 纽约州约翰·多伊
  2. 约翰·福,新泽西州
  3. 纽约州 XYZ

在这种情况下,如果搜索查询是“John NY”,那么结果应该具有类似的相关性

  1. 纽约州约翰·多伊
  2. 纽约州 XYZ
  3. 约翰·福,新泽西州

【问题讨论】:

  • 你能添加一些代码来显示你是如何构建索引的吗?
  • 你好守门员!我已经添加了代码和我的预期场景。

标签: c# lucene.net


【解决方案1】:

我无法弄清楚您认为您的方法有什么问题,但这是我用来测试的代码:

class Program
{
    static void Main(string[] args)
    {
        RAMDirectory dir = new RAMDirectory();

        IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer());

        AddDocument(writer, "John Doe", "NY");
        AddDocument(writer, "John Foo", "New Jersey");
        AddDocument(writer, "XYZ", "NY");

        writer.Commit();

        BooleanQuery query = new BooleanQuery();
        query.Add(new TermQuery(new Term("Name", "john")), BooleanClause.Occur.SHOULD);
        query.Add(new TermQuery(new Term("Location", "NY")), BooleanClause.Occur.SHOULD);

        IndexReader reader = writer.GetReader();

        IndexSearcher searcher = new IndexSearcher(reader);
        var hits = searcher.Search(query, null, 10);

        for (int i = 0; i < hits.totalHits; i++)
        {
            Document doc = searcher.Doc(hits.scoreDocs[i].doc);
            var explain = searcher.Explain(query, hits.scoreDocs[i].doc);
            Console.WriteLine("{0} - {1} - {2}", hits.scoreDocs[i].score, doc.ToString(), explain.ToString());
        }
    }

    private static void AddDocument(IndexWriter writer, string name, string address)
    {
        Document objDocument = new Document();
        Field objName = new Field("Name", name, Field.Store.YES, Field.Index.ANALYZED);
        Field objLocation = new Field("Location", address, Field.Store.YES, Field.Index.NOT_ANALYZED);
        objLocation.SetBoost(2f);
        objDocument.Add(objName);
        objDocument.Add(objLocation);
        writer.AddDocument(objDocument);
    }
}

此代码会按您希望的顺序返回结果。事实上,如果你排除了提升,它会按这个顺序返回它们。我不是 Lucene 评分方面的专家,但我相信这是因为您将 "NY" 与 "XYZ, NY" 完全匹配,而 "John" 查询是部分匹配。您可以通过 Explain 类阅读打印出的详细信息。

【讨论】:

  • 你好守门员!我试过你的代码。我发现我哪里出错了。我是这样查询的。 "QueryParser parser = new QueryParser("Name", objAnalyzer); Query query = parser.Parse("John NY"); Searcher objSearcher = new IndexSearcher(); Hits objHits = objSearcher.Search(query);"意思是,我只搜索“名称”字段,所以它没有考虑“位置”字段的提升因子。但问题是,用户将仅输入像“John NY”这样的搜索查询,其中我将无法提取“John”是 Name 而“NY”是 Location。那么有没有不指定字段的查询方式呢?
  • 这可能很难。是否可以为用户提供 2 个输入?您可以尝试在空格上拆分并对所有标记的每个字段进行通配符查询。
【解决方案2】:

你试过 MultiFieldQueryParser 吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-05
    • 2016-02-18
    • 2010-10-05
    • 1970-01-01
    相关资源
    最近更新 更多