【问题标题】:Adding words to query phrase should filter results in Lucene向查询短语添加单词应该过滤 Lucene 中的结果
【发布时间】:2012-02-29 12:23:29
【问题描述】:

如果可能,我会奖励 +100 这个问题,即使它已经被回答和接受了

我正在使用 Lucene 3.2,这是我的索引和代码中的内容:

  • 每个索引文档超过 10 个字段。
  • OR 查询短语中的操作数(即:“my lucene search”变为“my OR lucene OR search”)。
  • MultiFieldQueryParserOccur.SHOULD 在所有字段中。
  • 一个包含所有其他字段的特定 default 字段(如本解决方案 How to do a Multi field - Phrase search in Lucene? 中所建议的那样)。

我想达到什么目的?一种类似谷歌的搜索,让我解释一下:

  • 搜索所有字段
  • 评分结果(特定领域的提升等)
  • 向查询短语添加单词应该过滤结果

除了最后一个,我正在触及各个方面。我的问题如下:

  • 如果我只在包含所有其他字段的 默认 字段中进行搜索,我不会得到高分的结果
  • 仅使用 AND 操作数进行搜索,我得到的结果过于过滤,只得到在一个字段中具有 整个 查询短语的结果。
  • 仅使用 OR 操作数进行搜索非常适合查询中的一个单词,但是当向查询短语添加更多单词时,结果会显着增加,而不是过滤(就像 Google 所做的那样)。
  • 我不知道如何从另一个查询中筛选出一个查询

这是我对查询解析器的实际调用:

MultiFieldQueryParser.parse(
    Version.LUCENE_31,
    OrQueryWords, //query words separated with OR operand
    searchFields, //String[] searchFields; // all fields
    occurs, //Occur[] occurs; {Occur.SHOULD, Occur.SHOULD, etc..}
    getFullTextSession().getSearchFactory().getAnalyzer(Product.class)
);

此查询的toString() 打印如下内容:

(field1:"word1 word2" (field1:word1 field1:word2)) (field2:"word1 word2" (...)) etc.

现在我正在尝试添加 default 字段(包含所有其他字段的字段),其中查询词用 AND 操作数和 Occur.MUST 分隔:

MultiFieldQueryParser.parse(
    Version.LUCENE_31,
    AndQueryWords, //query words separated with AND operand
    new String[] {"defaultField"},
    new Occur[] {Occur.MUST},
    getFullTextSession().getSearchFactory().getAnalyzer(Product.class)
);

这个查询的toString() 打印出这个:

+(default:"word1 word2" (+default:word1 +default:word2))

如何交叉两个查询?有没有其他解决方案可以实现?

【问题讨论】:

    标签: java lucene


    【解决方案1】:

    我不确定你到底想达到什么目的,所以我将给你一些提示,告诉你在处理多字段多词查询时如何自定义评分。

    两个查询的交集

    您似乎对默认字段结果集上的合取查询以及对所有字段评分的析取查询感到满意。将后者用作主要查询,将前者用作过滤器,您可以两全其美。

    例如:

    Query mainQuery, filterQuery;
    
    BooleanQuery query = new BooleanQuery();
    
    // add the main query for scoring
    query.add(mainQuery, Occur.SHOULD);
    
    // prevent the filter query to participate in the scoring
    filter.setBoost(0);
    // make the filter query required
    query.add(filterQuery, Occur.MUST);
    

    最少应匹配子句

    如果对所有子句进行 AND 运算的限制性太强,并且对所有子句进行 OR 运算的限制性不够,那么您可以通过设置 minimum number of SHOULD clauses that must match 在两者之间做一些事情,以便文档出现在结果集中。

    那么困难的部分是找到正确的公式来计算必须匹配以获得最佳用户体验的 SHOULD 子句的最小数量。

    例如,假设您希望 SHOULD 子句的 3/4 的 ceil 匹配。从包含两个子句的查询开始并添加最多 5 个子句的子句将产生以下结果数量的演变。

    • 2 个术语 => ceil(2 * 3 / 4) = 2:所有子句必须匹配
    • 3 个词 => ceil(3 * 3 / 4) = 3: 3/4 个子句必须匹配(新的子句是必需的,less 结果)
    • 4 个词 => ceil(4 * 3 / 4) = 3:3/4 个子句必须匹配(其中一个子句是可选的,更多结果)
    • 5 个术语 => ceil(5 * 3 / 4) = 4: 4/5 个子句必须匹配(结果可能更多,也可能更少,取决于新术语与前 4 个术语的共现)李>

    无论如何,使用此功能,随着子句数量的增加,结果数量减少的唯一方法是使用纯合取查询。

    【讨论】:

    • 我喜欢这两种方法,我会尝试它们。如何构造 FilterQuery 以便它引用一个特定字段?谢谢!
    • 只需像往常一样手动构建此查询,或使用 MultiFieldQueryParser.parse 如您的问题一样。
    【解决方案2】:

    我用来解决类似问题的方法是根据分数限制结果数量。

    不幸的是,Lucene 没有提供开箱即用的此类功能,他们也不鼓励这种方法 (http://wiki.apache.org/lucene-java/ScoresAsPercentages)。主要担心的是分数的绝对值没有意义。

    我使用分数的相对值进行过滤:我选择了最高分数,然后从中计算出可接受的最低分数(比如maxScore / 5),然后只留下那些满足这个标准的结果。

    【讨论】:

    • 这是一个很好的方法,但我至少现在想避免它。如果没有符合查询的结果,我会显示类似“没有结果,也许你想说‘随便什么’”之类的内容
    猜你喜欢
    • 1970-01-01
    • 2018-09-25
    • 2018-02-15
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    相关资源
    最近更新 更多