【问题标题】:How to include prefixLength in Elasticsearch query built using HibernateSearch QueryDSL如何在使用 HibernateSearch QueryDSL 构建的 Elasticsearch 查询中包含 prefixLength
【发布时间】:2019-04-01 14:42:33
【问题描述】:

我们在 Elasticsearch 5.6.6 服务器上使用 Hibernate Search 5.10.3.Final。

在创建要传递给 FullTextSession::createFullTextQuery 的模糊查询时,我设置了 editDistance 和 prefixLength,但我从日志中注意到发送到 Elasticsearch 的实际查询不包含 prefixLength。

这段代码是从多个单独的方法中提取的,但这是基本的工作流程:

QueryBuilder qb = fts.getSearchFactory()
    .buildQueryBuilder()
    .forEntity(Vendor.class)
    .get();

BooleanJunction namesBool = qb.bool();

String field = "vendorNames.vendorName";
String token = "rooster";

int editDistance = getEditDistance(token); //returns 1 for "rooster"
int prefixLength = getPrefixLength(token); //returns 1 for "rooster"

namesBool.must(
    qb.keyword()
        .fuzzy() //returns FuzzyContext
        .withEditDistanceUpTo(editDistance)
        .withPrefixLength(prefixLength)
        .onField(field)
        .matching(token)
        .createQuery()
);


// ...
// calling FullTextSession::createFullTextQuery

当术语“公鸡”通过此方法发送时,它的 editDistance(模糊度)为 1,prefixLength 为 1。

检查日志并查看发送到 ES 的内容,我希望在“fuzziness”正下方看到“prefix_length”,但它不存在:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "vendorNames.vendorName": {
            "query": "rooster",
            "fuzziness": 1
          }
        }
      }
    }
  }
  1. 为什么 FuzzyContext 允许设置 prefixLength 但不使用它?
  2. 尝试包含 prefixLength 是否真的值得 ES 性能提升(我测试了直接对 ES 的 REST 查询调用,无论有无 prefixLength,但没有注意到响应时间差异)?
  3. 如何让 prefixLength 包含在发送到 ES 的实际查询中?

【问题讨论】:

    标签: java elasticsearch hibernate-search


    【解决方案1】:

    为什么 FuzzyContext 允许设置 prefixLength 但不使用它?

    这是 Elasticsearch 集成的错误,但直到现在才报告:谢谢!我们将在下一个开发周期中尝试修复它:HSEARCH-3545

    尝试包含 prefixLength 是否真的值得 ES 性能提升(我测试了直接对 ES 的 REST 查询调用,无论有没有 prefixLength 并且没有注意到响应时间差异)?

    prefixLength 更多的是关于结果的相关性而不是性能。这个想法是,如果用户给我们一个 10 个字符长的单词,我们可能会得到很多模糊匹配,其中大部分可能是不相关的。通过忽略前 5 个字符(例如),我们将集中在词尾附近的模糊性,这可能不太相关(想想“theory”/“theories”、“构成”/“构成”等):这样我们会得到更少的模糊匹配,但它们会更相关。

    至少理论上是这样的:)

    如何让 prefixLength 包含在发送到 ES 的实际查询中?

    如果不需要支持多个token,可以直接创建FuzzyQuery

    BooleanJunction namesBool = qb.bool();
    String field = "vendorNames.vendorName";
    String token = "rooster";
    int editDistance = getEditDistance(token); //returns 1 for "rooster"
    int prefixLength = getPrefixLength(token); //returns 1 for "rooster"
    
    namesBool.must(
        new FuzzyQuery(new Term(field, token), editDistance, prefixLength)
    );
    

    这个查询将被正确翻译。

    如果您确实需要支持多个令牌(即您想要一个 fuzzy match query,而不仅仅是一个 fuzzy query),那么您唯一的解决方案是将 whole 查询编写为 JSON 并使用org.hibernate.search.elasticsearch.ElasticsearchQueries#fromJson:

    String field = "vendorNames.vendorName";
    String token = "rooster";
    int editDistance = getEditDistance(token); //returns 1 for "rooster"
    int prefixLength = getPrefixLength(token); //returns 1 for "rooster"
    
    QueryDescriptor queryDescriptor = ElasticsearchQueries.fromJson(
    "{"
      + "\"query\": {"
        + "\"bool\": {"
          + "\"must\": {"
            + "\"match\": {"
              + "\"" + field + "\": {"
                + "\"query\": \"" + token + "\","
                + "\"fuzziness\": " + editDistance + ","
                + "\"prefix_length\": " + prefixLength
              + "}"
            + "}"
          + "}"
        + "}"
      + "}"
    + "}"
    );
    
    List<?> result = session.createFullTextQuery( queryDescriptor, MyEntity.class )
                    .list();
    

    是的,这是一口……我们正在改进 Hibernate Search 6 中的内容。

    【讨论】:

    • 很高兴知道!谢谢,我想我可以使用您关于构建新 FuzzyQuery 的建议。
    • 您能否完成关于以“如果用户给我们的想法是”开头的 prefixLength 的解释?我认为它被砍掉了。
    • 对,对不起。完成。
    • 这可能会变成一个单独的问题,但是按照建议从 Match 查询更改为 FuzzyQuery 时,我注意到转置现在默认为 false 并使用 new FuzzyQuery(new Term(field, token), editDistance, prefixLength, FuzzyQuery.defaultMaxExpansions, true),它不会被转换为 ES查询(具有讽刺意味的是,类似于在匹配查询中忽略前缀长度)。有什么建议吗?
    • 恐怕不行。如果您想要换位,您在搜索 5 中的唯一选择是将整个查询写为 JSON...
    猜你喜欢
    • 2017-04-08
    • 1970-01-01
    • 2014-07-13
    • 2017-03-24
    • 2019-03-27
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多