【问题标题】:Elasticsearch prefix queryElasticsearch 前缀查询
【发布时间】:2021-05-06 13:50:56
【问题描述】:

如何在 Elasticsearch 中进行前缀搜索?

例如,如果我有以下索引文档:

[{
        "id": "1",
        "key": "abc",
        "foo": [1, 2, 3]
    },
    {
        "id": "2",
        "key": "ab",
        "foo": [4]
    },
    {
        "id": "3",
        "key": "xyz",
        "foo": [9, 10]
    },
    {
        "id": "4",
        "key": "abcd",
        "foo": [12]
    }
]

现在我想查询值为“abcdef”的属性“key”。

我希望以下文档与查询匹配。

document id matched reason
"1" YES "abc" is a prefix of "abcdef"
"2" YES "ab" is a prefix of "abcdef"
"3" NO "xyz" is not a prefix of "abcdef"
"4" YES "abcd" is a prefix of "abcdef"

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    使用edge-ngram tokenizer(或token filter)是正确的,但您应该只在搜索时应用它,因为文档已经包含您要搜索的前缀。

    所以你的索引设置和映射应该是这样的:

    PUT test
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "prefix_analyzer": {
              "tokenizer": "prefix_tokenizer"
            }
          },
          "tokenizer": {
            "prefix_tokenizer": {
              "type": "edge_ngram",
              "min_gram": 2,
              "max_gram": 6,
              "token_chars": [
                "letter",
                "digit"
              ]
            }
          }
        },
        "index": {
          "max_ngram_diff": 10
        }
      },
      "mappings": {
        "properties": {
          "key": {
            "type": "text",
            "analyzer": "keyword",
            "search_analyzer": "prefix_analyzer"
          }
        }
      }
    }
    

    然后,您的搜索查询可能如下所示:

    POST test/_search
    {
      "query": {
        "match": {
          "key": "abcdef"
        }
      }
    }
    

    将会发生的是输入标记abcdef 将被标记为:

    • ab
    • abc
    • abcd
    • abcde
    • abcdef

    在结果中你会得到:

    • 第一个标记将匹配文档 2
    • 第二个标记将匹配文档 1
    • 第三个标记将匹配文档 4

    【讨论】:

      【解决方案2】:

      您可以使用edge_ngram tokenizer 查询值为“abcdef”的属性“key”

      添加一个工作示例

      索引映射:

      {
        "settings": {
          "analysis": {
            "analyzer": {
              "my_analyzer": {
                "tokenizer": "my_tokenizer"
              }
            },
            "tokenizer": {
              "my_tokenizer": {
                "type": "edge_ngram",
                "min_gram": 2,
                "max_gram": 6,
                "token_chars": [
                  "letter",
                  "digit"
                ]
              }
            }
          },
          "max_ngram_diff": 10
        },
        "mappings": {
          "properties": {
            "key": {
              "type": "text",
              "analyzer": "my_analyzer"
            }
          }
        }
      }
      

      搜索查询:

      {
        "query": {
         "match":{
           "key":"abcdef"
         }
        }
      }
      

      搜索结果:

      "hits": [
            {
              "_index": "67419529",
              "_type": "_doc",
              "_id": "4",
              "_score": 1.8710749,
              "_source": {
                "id": "4",
                "key": "abcd",
                "foo": [
                  12
                ]
              }
            },
            {
              "_index": "67419529",
              "_type": "_doc",
              "_id": "1",
              "_score": 1.0498221,
              "_source": {
                "id": "1",
                "key": "abc",
                "foo": [
                  1,
                  2,
                  3
                ]
              }
            },
            {
              "_index": "67419529",
              "_type": "_doc",
              "_id": "2",
              "_score": 0.44839138,
              "_source": {
                "id": "2",
                "key": "ab",
                "foo": [
                  4
                ]
              }
            }
          ]
      

      【讨论】:

      • 请注意,最好仅在搜索时使用该分析器,因为您只想标记输入项而不是文档本身中的值。这是一种“反向”匹配,前缀在文档中,完整术语在查询中(通常是相反的方式)
      • @Val yes 仅在搜索时使用分析器是有意义的。谢谢!
      • @Rahul 如果答案帮助您解决了问题,那么请不要忘记接受并投票赞成答案:-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 2015-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多