【问题标题】:How to match on prefix in Elasticsearch如何在 Elasticsearch 中匹配前缀
【发布时间】:2012-08-24 22:09:16
【问题描述】:

假设在我的弹性搜索索引中,我有一个名为“dots”的字段,其中包含一串标点分隔的单词(例如“first.second.third”)。

我需要搜索例如“first.second”,然后获取其“dots”字段包含正好是“first.second”或以“first.second”开头的字符串的所有条目。

我无法理解文本查询的工作原理,至少我无法创建一个可以完成这项工作的查询。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    Elasticsearch 有 Path Hierarchy Tokenizer 正是为此类用例创建的。以下是如何为您的索引设置它的示例:

    # Create a new index with custom path_hierarchy analyzer 
    # See http://www.elasticsearch.org/guide/reference/index-modules/analysis/pathhierarchy-tokenizer.html
    curl -XPUT "localhost:9200/prefix-test" -d '{
        "settings": {
            "analysis": {
                "analyzer": {
                    "prefix-test-analyzer": {
                        "type": "custom",
                        "tokenizer": "prefix-test-tokenizer"
                    }
                },
                "tokenizer": {
                    "prefix-test-tokenizer": {
                        "type": "path_hierarchy",
                        "delimiter": "."
                    }
                }
            }
        },
        "mappings": {
            "doc": {
                "properties": {
                    "dots": {
                        "type": "string",
                        "analyzer": "prefix-test-analyzer",
                        //"index_analyzer": "prefix-test-analyzer", //deprecated
                        "search_analyzer": "keyword"
                    }
                }
            }
        }
    }'
    echo
    # Put some test data
    curl -XPUT "localhost:9200/prefix-test/doc/1" -d '{"dots": "first.second.third"}'
    curl -XPUT "localhost:9200/prefix-test/doc/2" -d '{"dots": "first.second.foo-bar"}'
    curl -XPUT "localhost:9200/prefix-test/doc/3" -d '{"dots": "first.baz.something"}'
    curl -XPOST "localhost:9200/prefix-test/_refresh"
    echo
    # Test searches. 
    curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{
        "query": {
            "term": {
                "dots": "first"
            }
        }
    }'
    echo
    curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{
        "query": {
            "term": {
                "dots": "first.second"
            }
        }
    }'
    echo
    curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{
        "query": {
            "term": {
                "dots": "first.second.foo-bar"
            }
        }
    }'
    echo
    curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true&q=dots:first.second"
    echo
    

    【讨论】:

    • 对不起,直到现在才看到你的帖子!!非常感谢 :) 我一有时间就会调查一下!
    • 如何在我的 Java 代码中执行设置和映射?
    • client.admin().indices().prepareCreate("test").addMapping("type1", mapping).setSettings(settings).execute().actionGet();
    • 假设您还有一个文档'{"dots": "first.second.third.fourth"}',您将如何仅获取“first.second”级别的文档,即[ “first.second.third”,“first.second.foo-bar”]?本质上,我想获取“first.second”模块中的所有文档,并且不想让孩子们在他们之下,因为表面上看起来很多。
    【解决方案2】:

    还有一种更简单的方法,正如 elasticsearch documentation 中指出的那样:

    只需使用:

    {
        "text_phrase_prefix" : {
            "fieldname" : "yourprefix"
        }
    }
    

    或从 0.19.9 开始:

    {
        "match_phrase_prefix" : {
            "fieldname" : "yourprefix"
        }
    }
    

    代替:

    {   
        "prefix" : { 
            "fieldname" : "yourprefix" 
    }
    

    【讨论】:

      【解决方案3】:

      看看prefix queries

      $ curl -XGET 'http://localhost:9200/index/type/_search' -d '{
          "query" : {
              "prefix" : { "dots" : "first.second" }
          }
      }'
      

      【讨论】:

      • This 在新索引上工作。你的索引上有特殊的映射吗?也许你应该尝试一个新的、干净的索引。
      • 使用前缀搜索或路径层次分词器有效率差异吗?
      • @JaySullivan prefix 查询是术语查询,所以没有分析 => 这么快。但没有分析。
      【解决方案4】:

      您应该使用 commodin 字符进行查询,如下所示:

      $ curl -XGET http://localhost:9200/myapp/index -d '{
          "dots": "first.second*"
      }'
      

      更多关于语法的例子:http://lucene.apache.org/core/old_versioned_docs/versions/2_9_1/queryparsersyntax.html

      【讨论】:

      • 您发布的 JSON 实际上不是查询,您能更正一下吗?
      【解决方案5】:

      我正在寻找类似的解决方案 - 但只匹配一个前缀。我发现@imtov 的answer 让我快到了那里,但有一个变化 - 切换分析器:

      "mappings": {
          "doc": {
              "properties": {
                  "dots": {
                      "type": "string",
                      "analyzer": "keyword",
                      "search_analyzer": "prefix-test-analyzer"
                  }
              }
          }
      }
      

      而不是

      "mappings": {
          "doc": {
              "properties": {
                  "dots": {
                      "type": "string",
                      "index_analyzer": "prefix-test-analyzer",
                      "search_analyzer": "keyword"
                  }
              }
          }
      }
      

      这样添加:

      '{"dots": "first.second"}'
      '{"dots": "first.third"}'
      

      将仅添加这些完整令牌,而不存储 firstsecondthird 令牌。

      还在搜索中

      first.second.anyotherstring
      first.second
      

      只会正确返回第一个条目:

      '{"dots": "first.second"}'
      

      不完全是您要求的,但在某种程度上相关,所以我认为可以帮助某人。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-21
        • 2019-09-09
        • 2021-02-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多