【问题标题】:bidirectional match on elasticsearchelasticsearch上的双向匹配
【发布时间】:2017-09-10 12:32:24
【问题描述】:

我已经索引了一个术语列表,现在我想查询其中的一些

说我已经索引了'dog food','red dog','dog','food','cats'

如何创建精确的双向匹配查询。即:我希望在搜索“狗”时获得术语 dog 而不是其他术语(因为它们不匹配)。


我想到的一个原始解决方案是用它们的长度(Words-wise)对术语进行索引,然后在使用长度 X 搜索查询时将其限制为长度 X 的术语。但它似乎过于复杂。

【问题讨论】:

    标签: elasticsearch solr lucene nosql


    【解决方案1】:

    创建一个自定义分析器来小写和规范您的搜索词。这就是你的索引:

    {
      "settings" : {
        "analysis" : {
          "analyzer" : {
            "my_analyzer_keyword" : {
              "type" : "custom",
              "tokenizer" : "keyword",
              "filter" : [
                "asciifolding",
                "lowercase"
              ]
            }
          }
        }
      },
      "mappings" : {
        "your_type" : {
          "properties" : {
            "name" : {
              "type" : "string",
              "analyzer" : "my_analyzer_keyword"
            }
          }
        }
      }
    }
    

    因此,如果您已将'dog' 编入索引,并且用户输入DogdogDOG,它将仅匹配dog'dog food' 不会被恢复。

    【讨论】:

      【解决方案2】:

      只需将字段的index 属性设置为not_analyzed,您的查询应使用term 过滤器来搜索文本。

      根据 Evaldas 的建议,在下面找到一个更完整的解决方案,该解决方案还保留使用 standard 分析器索引的原始值,但使用带有小写版本术语的子字段:

      PUT /test
      {
        "settings": {
          "analysis": {
            "analyzer": {
              "my_keyword_lowercase_analyzer": {
                "type": "custom",
                "filter": [
                  "lowercase"
                ],
                "tokenizer": "keyword"
              }
            }
          }
        },
        "mappings": {
          "asset": {
            "properties": {
              "name": {
                "type": "string",
                "fields": {
                  "case_ignore": {
                    "type": "string",
                    "analyzer": "my_keyword_lowercase_analyzer"
                  }
                }
              }
            }
          }
        }
      }
      
      POST /test/asset/1
      {
        "name":"dog"
      }
      POST /test/asset/2
      {
        "name":"dog food"
      }
      POST /test/asset/3
      {
        "name":"red dog"
      }
      
      GET /test/asset/_search
      {
        "query": {
          "match": {
            "name.case_ignore": "Dog"
          }
        }
      }
      

      【讨论】:

      • 不会那样做。如果是大写字母。
      • @EvaldasBuinauskas 我在 OP 中没有看到任何大写字母 ;-)。
      • 存储明智的是。但是用户可以输入任何东西! :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多