elasticsearch - 如何使用NGram过滤器自动完成对多值字段的Elasticsearch术语聚合?

标签 elasticsearch autocomplete kibana n-gram elasticsearch-aggregation

我正在做我的自动完成项目,这是Elasticsearch的新项目。我已使用Edge NGram过滤器进行自动补全。
我试图获得自动完成的唯一结果,所以我对所有字段都使用了术语汇总。
对于具有1个值的字段,我得到了很好的结果,但是对于具有多个值的字段,我得到了很好的结果..如果查询与该字段中的至少一个值匹配..它为我提供了该字段的所有值(无论查询是否匹配其他值)。

我在服装索引下的设置和映射是:

PUT /garments
{
  "settings" : 
  {
    "number_of_replicas": 3,
    "number_of_shards": 2,
    "analysis": 
    {
      "analyzer": 
      {
        "autocomplete": 
        {
          "tokenizer": "autocomplete",
          "filter": 
          [
            "lowercase"
          ]
        },
        "autocomplete_search": 
        {
          "tokenizer": "lowercase"
        }
      },
      "tokenizer": 
      {
        "autocomplete": 
        {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": 
          [
            "letter"
          ]
        }
      }

    }
  },
  "mappings":
  {
    "properties":
    {
      "color": 
      {
        "type": "text",
        "analyzer": "autocomplete",
        "search_analyzer": "autocomplete_search",
        "fields": 
        {
          "keyword": 
          { 
            "type": "keyword"
          }
        }

      }
........
........
........
   }
}

(请注意我正在使用文本类型)
假设我在文档中有一个颜色字段,该字段具有多个值,如:[“” blue“,” black“,” orange“,” marble“,” jet black“]
我的搜索查询是:
GET /garments/_search
{
  "size": 0, 
  "query": 
  {
      "query_string": {
        "query": "bl"
      }
  },
  "aggs":
  {
    "Term_aggregation": 
    {
      "terms": 
      {
        "field": "color.keyword", 
        "size": 100
      }
    }
  }
}

这给了我所有的输出,即:“蓝色”,“黑色”,“橙色”,“大理石”,“黑色”。
但是我只想将蓝色,黑色,黑色作为结果(查询为“bl”)。
后来
我用了
"include": " .*bl.*" 

用我的话说是滤镜aggs ..这给了我蓝色,黑色,大理石,深黑色作为结果。.包括滤镜是区分大小写的...请帮助!

最佳答案

如果要对关键字字段进行不区分大小写的匹配,则可以将normalizer与小写过滤器一起使用

The normalizer property of keyword fields is similar to analyzer except that it guarantees that the analysis chain produces a single token.


{
  "settings": {
    "analysis": {
      "normalizer": {
        "lowercase_normalizer": {
          "type": "custom",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "color": {
        "type": "text",
        "analyzer": "autocomplete",
        "search_analyzer": "autocomplete_search",
        "fields": {
          "keyword": {
            "type": "keyword",
            "normalizer": "lowercase_normalizer"
          }
        }
      }
    }
  }
}

“include”:“.bl。”即使实际值包含大写字母也可以使用

编辑1

根据您的评论,如果您不想在术语中使用包含。您需要使用nested type索引颜色,以便将每种颜色都视为单独的对象

对应:
PUT index64
{
  "settings": {
    "number_of_replicas": 3,
    "number_of_shards": 2,
    "analysis": {
      "analyzer": {
        "autocomplete": {
          "tokenizer": "autocomplete",
          "filter": [
            "lowercase"
          ]
        },
        "autocomplete_search": {
          "tokenizer": "lowercase"
        }
      },
      "tokenizer": {
        "autocomplete": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "color": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "text",
            "analyzer": "autocomplete",
            "search_analyzer": "autocomplete_search",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
  }
}


查询:
POST index64/_doc
{
  "color": [
    {
      "name": "blue"
    },
    {
      "name": "black"
    },
    {
      "name": "orange"
    },
    {
      "name": "marble"
    },
    {
      "name": "jet black"
    }
  ]
}


结果:
GET index64/_search
{
  "size": 0, 
  "aggs": {
    "color": {
      "nested": {
        "path": "color"
      },
      "aggs": {
        "select_color": {
          "filter": {
            "match":{
              "color.name":"bl"
            }
          },
          "aggs": {
            "distinct_colors": {
              "terms": {
                "field": "color.name.keyword",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

结果
"aggregations" : {
    "color" : {
      "doc_count" : 5,
      "select_color" : {
        "doc_count" : 3,
        "distinct_colors" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "black",
              "doc_count" : 1
            },
            {
              "key" : "blue",
              "doc_count" : 1
            },
            {
              "key" : "jet black",
              "doc_count" : 1
            }
          ]
        }
      }
    }
  }

关于elasticsearch - 如何使用NGram过滤器自动完成对多值字段的Elasticsearch术语聚合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61949730/

相关文章:

elasticsearch - 如何搜索没有特定字段的文档/记录?

python - Elasticsearch不返回单个单词查询的结果

elasticsearch - Elasticsearch:使用数组处理JSON

google-chrome - 如何禁用Chrome自动填充功能(2020年之后)

javascript - 为什么我的自动完成功能不起作用?

kibana - 如何在 Kibana ElasticSearch open distro 中引发警报的消息中使用触发器变量

elasticsearch - ElasticSearch将1.x升级到6.x

elasticsearch - 即使有0个未分配的分片,Elasticsearch集群的状态仍为黄色

elasticsearch - Filebeat > 是否可以在没有 Logstash 的情况下通过 Filebeat 将数据发送到 Elasticsearch

ios - CustomTextField - 自动完成/自动更正不会在点击时关闭