【问题标题】:Getting results for multi_match cross_fields query in elasticsearch with custom analyzer使用自定义分析器在 elasticsearch 中获取 multi_match cross_fields 查询的结果
【发布时间】:2017-09-15 14:30:33
【问题描述】:

我有一个带有产品的弹性搜索 5.3 服务器。 每个产品都有一个 14 位数的产品代码,必须通过以下规则进行搜索。完整的代码应与仅包含后 9 位、后 6 位、后 5 位或后 4 位的搜索词匹配。

为了实现这一点,我创建了一个自定义分析器,它使用模式捕获标记过滤器在索引时创建适当的标记。这似乎工作正常。 _analysis API 显示创建了正确的术语。

为了从弹性搜索中获取文档,我使用 multi_match cross_fields bool 查询同时搜索多个字段。

当我的查询字符串的一部分与产品代码匹配,另一部分与任何其他字段匹配时,不会返回任何结果,但是当我分别搜索每个部分时,会返回适当的结果。此外,当我有多个部分跨越除产品代码之外的任何字段时,将返回正确的结果。

我的映射和分析器:

PUT /store
{
    "mappings": {
        "products":{
            "properties":{
                "productCode":{
                    "analyzer": "ProductCode",
                    "search_analyzer": "standard",
                    "type": "text"
                },
                "description": {
                    "type": "text"
                },
                "remarks": {
                    "type": "text"
                }
            }
        }
    },
    "settings": {
        "analysis": {
            "filter": {
                "ProductCodeNGram": {
                    "type": "pattern_capture",
                    "preserve_original": "true",
                    "patterns": [
                        "\\d{5}(\\d{9})",
                        "\\d{8}(\\d{6})",
                        "\\d{9}(\\d{5})",
                        "\\d{10}(\\d{4})"
                    ]
                }
            },
            "analyzer": {
                "ProductCode": {
                    "filter": ["ProductCodeNGram"],
                    "type": "custom",
                    "preserve_original": "true",
                    "tokenizer": "standard"
                }
            }
        }
    }
}

查询

GET /store/products/_search
{
    "query": {
        "bool": {
            "must": [
               {
                   "multi_match": {
                      "query": "[query_string]",
                      "fields": ["productCode", "description", "remarks"],
                      "type": "cross_fields",
                      "operator": "and"
                   }
               }
            ]
        }
    }
}

样本数据

POST /store/products
{
    "productCode": "999999123456789",
    "description": "Foo bar",
    "remarks": "Foobar"
}

以下查询字符串均返回一个结果:

“456789”、“foo”、“foobar”、“foo foobar”。

但是 query_string "foo 456789" 没有返回任何结果。

我很好奇为什么最后一次搜索没有返回任何结果。我相信它应该这样做。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    问题是您正在使用不同的分析器对字段进行 cross_fields。交叉字段仅适用于使用相同分析器的字段。实际上,它在执行交叉字段之前按分析器对字段进行分组。您可以在此文档中找到更多信息。

    https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#_literal_cross_field_literal_and_analysis

    【讨论】:

      【解决方案2】:

      虽然cross_fields 需要在它所操作的字段中使用相同的分析器,但我很幸运地使用了tie_breaker 参数来允许对其他字段(使用不同分析器)进行加权以获得总分。 这还有一个额外的好处,就是允许在最终得分中计算每个字段的提升。

      这是一个使用您的查询的示例:

      GET /store/products/_search
      {
          "query": {
              "bool": {
                  "must": [
                     {
                         "multi_match": {
                            "query": "[query_string]",
                            "fields": ["productCode", "description", "remarks"],
                            "type": "cross_fields",
                            "tie_breaker": 1   # You may need to tweak this
                         }
                     }
                  ]
              }
          }
      }
      

      我还删除了operator 字段,因为我相信使用“AND”运算符会导致没有相同分析器的字段被错误地评分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多