首页 > 解决方案 > ElasticSearch 多匹配子字符串搜索

问题描述

我必须结合两个过滤器来匹配要求: - r.status 字段中的特定值列表 - 多个文本字段之一包含该值。结果查询(使用 using Nest,但没关系)如下所示:

{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "must": [
              {
                "term": {
                  "isActive": {
                    "value": true
                  }
                }
              },
              {
                "nested": {
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "terms": {
                            "r.status": [
                              "VALUE_1",
                              "VALUE_2",
                              "VALUE_3"
                            ]
                          }
                        },
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "r.g.firstName": {
                                    "type": "phrase",
                                    "query": "SUBSTRING_VALUE"
                                  }
                                }
                              },
                              {
                                "match": {
                                  "r.g.lastName": {
                                    "type": "phrase",
                                    "query": "SUBSTRING_VALUE"
                                  }
                                }
                              }
                            ]
                          }
                        }
                      ]
                    }
                  },
                  "path": "r"
                }
              }
            ]
          }
        }
      ]
    }
  }
}

还尝试了 multi_match 查询:

{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "must": [
              {
                "term": {
                  "isActive": {
                    "value": true
                  }
                }
              },
              {
                "nested": {
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "terms": {
                            "r.status": [
                              "VALUE_1",
                              "VALUE_2",
                              "VALUE_3"
                            ]
                          }
                        },
                        {
                          "multi_match": {
                            "query": "SUBSTRING_VALUE",
                            "fields": [
                              "r.g.firstName",
                              "r.g.lastName"
                            ]
                          }
                        }
                      ]
                    }
                  },
                  "path": "r"
                }
              }
            ]
          }
        }
      ]
    }
  }
}

FirstNameLastName在索引映射中配置为text

"firstName": {
  "type": "text"
},
"lastName": {
  "type": "text"
}

Elastic 提供了很多全文搜索选项:multi_matchphrasewildcards。但在我的情况下,它们都失败了,在我的文本字段中查找子字符串。(terms查询和isActive一个运行良好,我只是尝试只运行它们)。

我还有什么选择,或者我可能在哪里犯了错误?

UPD:组合通配符对我有用,但这样的查询看起来很难看。寻找更优雅的解决方案。

标签: elasticsearch

解决方案


elasticsearch方式是使用ngram tokenizer。

ngram 分析器将使用滑动窗口拆分您的术语。例如,输入“Hello World”将生成以下术语:

  • 赫尔
  • 地狱
  • 你好
  • 埃尔
  • 你好
  • ...
  • 工作
  • 世界
  • 奥尔
  • ...

您可以配置滑动窗口的最小和最大尺寸(在示例中最小尺寸为 3)。生成子术语后,您可以在子字段中使用匹配查询。

还有一点,mustfilter. 如果您对分数感兴趣,则应始终使用,must否则使用filter. 阅读这篇文章以获得良好的理解。


推荐阅读