使用自定义分析器在elasticsearch中获取multi_match cross_fields查询的结果

问题描述 投票:0回答:2

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

为了实现这一点,我创建了一个自定义分析器,它使用模式捕获令牌过滤器在索引时创建适当的标记。这似乎工作正常。 _analyse 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
2个回答
2
投票

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

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


0
投票

虽然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”运算符会导致不具有相同分析器的字段得分不当。

© www.soinside.com 2019 - 2024. All rights reserved.