代码之家  ›  专栏  ›  技术社区  ›  nlv

聚合中的弹性同义词用法

  •  0
  • nlv  · 技术社区  · 7 年前

    :

    使用的弹性版本:2.3.1

    我有一个这样配置的弹性索引

    PUT /my_index
    {
      "settings": {
        "analysis": {
          "filter": {
            "my_synonym_filter": {
              "type": "synonym", 
              "synonyms": [ 
                "british,english",
                "queen,monarch"
              ]
            }
          },
          "analyzer": {
            "my_synonyms": {
              "tokenizer": "standard",
              "filter": [
                "lowercase",
                "my_synonym_filter" 
              ]
            }
          }
        }
      }
    }
    

    这很好,当我查询文档并使用查询词时“ 英语 “或” “我得到了所有匹配的文档 英国的 . 当我在过滤器聚合中使用同义词时,它不起作用。例如

    在我的索引中,我有5个文件,其中3个有君主,2个有女王

    POST /my_index/_search
    {
      "size": 0,
      "query" : {
          "match" : {
             "status.synonym":{
                "query": "queen",
                "operator": "and"
             }
          }
       },
         "aggs" : {
            "status_terms" : {
                "terms" : { "field" : "status.synonym" }
            },
            "monarch_filter" : {
                "filter" : { "term": { "status.synonym": "monarch" } }
            }
        },
       "explain" : 0
    }
    

    点击总数:

    • 5个文档计数(如预期,太棒了!)
    • 状态条件:女王有5个文档(如预期,太棒了!)
    • Monarch筛选器:0文档计数

    我尝试了不同的同义词过滤器配置:

    • 女王,君主
    • 女王,君主=>女王,君主

    但上述情况并没有改变结果。我想得出结论,也许你只能在查询时使用过滤器,但如果术语聚合有效,为什么不应该过滤,因此我认为我的同义词过滤器配置是错误的。可以找到更广泛的同义词过滤器示例 here .

    问题

    如何在过滤器聚合中使用/配置同义词?

    复制上述案例的示例 : 1、创建和配置索引:

    PUT /my_index
    {
      "settings": {
        "analysis": {
          "filter": {
            "my_synonym_filter": {
              "type": "synonym",
              "synonyms": [
                "wlh,wellhead=>wellwell"
              ]
            }
          },
          "analyzer": {
            "my_synonyms": {
              "tokenizer": "standard",
              "filter": [
                "lowercase",
                "my_synonym_filter"
              ]
            }
          }
        }
      }
    }
    
    PUT my_index/_mapping/job
    {
      "properties": {
        "title":{
          "type": "string",
          "analyzer": "my_synonyms"
        }
      }
    }
    

    2、放置两份文件:

    PUT my_index/job/1
    {
        "title":"wellhead smth else"
    }
    
    PUT my_index/job/2
    {
        "title":"wlh other stuff"
    }
    

    3、执行搜索 wlh公司 威尔威尔 和一个不应有0计数的过滤器:

    POST my_index/_search
    {
      "size": 0,
      "query" : {
          "match" : {
             "title":{
                "query": "wlh",
                "operator": "and"
             }
          }
       },
         "aggs" : {
            "wlhAggs" : {
                "terms" : { "field" : "title" }
            },
            "wlhFilter" : {
                "filter" : { "term": { "title": "wlh"     } }
            }
        },
       "explain" : 0
    }
    

    此查询的结果是:

       {
       "took": 8,
       "timed_out": false,
       "_shards": {
          "total": 5,
          "successful": 5,
          "failed": 0
       },
       "hits": {
          "total": 2,
          "max_score": 0,
          "hits": []
       },
       "aggregations": {
          "wlhAggs": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
                {
                   "key": "wellwell",
                   "doc_count": 2
                },
                {
                   "key": "else",
                   "doc_count": 1
                },
                {
                   "key": "other",
                   "doc_count": 1
                },
                {
                   "key": "smth",
                   "doc_count": 1
                },
                {
                   "key": "stuff",
                   "doc_count": 1
                }
             ]
          },
          "wlhFilter": {
             "doc_count": 0
          }
       }
    }
    

    这就是我的问题,wlhFilter中应该至少有1个文档计数。

    2 回复  |  直到 7 年前
        1
  •  4
  •   Byron Voorbach    7 年前

    我的时间很短,所以如果需要的话,我可以在今天/明天晚些时候详细阐述一下。但以下几点应该有效:

    DELETE /my_index
    PUT /my_index
    {
      "settings": {
        "analysis": {
          "filter": {
            "my_synonym_filter": {
              "type": "synonym", 
              "synonyms": [ 
                "british,english",
                "queen,monarch"
              ]
            }
          },
          "analyzer": {
            "my_synonyms": {
              "tokenizer": "standard",
              "filter": [
                "lowercase",
                "my_synonym_filter" 
              ]
            }
          }
        }
      },
      "mappings": {
        "test": {
          "properties": {
            "title": {
              "type": "text",
              "analyzer": "my_synonyms",
              "fielddata": true
            }
          }
        }
      }
    }
    POST my_index/test/1
    {
      "title" : "the british monarch"
    }
    
    GET my_index/_search
    {
      "query": {
        "match": {
          "title": "queen"
        }
      }
    }
    
    GET my_index/_search
    {
      "query": {
        "match": {
          "title": "queen"
        }
      }, 
      "aggs": {
        "queen_filter": {
          "filter": {
            "term": {
              "title": "queen"
            }
          }
        },
        "monarch_filter": {
          "filter": {
            "term": {
              "title": "monarch"
            }
          }
        }
      }
    }
    

    你能分享一下你为你的 status.synonym 领域

    编辑:V2

    过滤器输出为0的原因是Elasticsearch中的过滤器从未经过分析阶段。这是为了精确匹配。

    聚合中的标记“wlh”不会转换为“wellwell”,这意味着它不会出现在反向索引中。这是因为,在索引期间,您的“wlh”被翻译为“wellwell”。 为了实现您想要的,您必须将数据索引到一个单独的字段中,并相应地调整过滤器。

    您可以尝试以下方式:

    DELETE my_index
    PUT /my_index
    {
      "settings": {
        "number_of_shards": 1, 
        "number_of_replicas": 0, 
        "analysis": {
          "filter": {
            "my_synonym_filter": {
              "type": "synonym",
              "synonyms": [
                "wlh,wellhead=>wellwell"
              ]
            }
          },
          "analyzer": {
            "my_synonyms": {
              "tokenizer": "standard",
              "filter": [
                "lowercase",
                "my_synonym_filter"
              ]
            }
          }
        }
      },
      "mappings": {
        "job": {
          "properties": {
            "title": {
              "type": "string",
              "fields": {
                "synonym": {
                  "type": "string",
                  "analyzer": "my_synonyms"
                }
              }
            }
          }
        }
      }
    }
    
    PUT my_index/job/1
    {
        "title":"wellhead smth else"
    }
    
    PUT my_index/job/2
    {
        "title":"wlh other stuff"
    }
    
    POST my_index/_search
    {
      "size": 0,
      "query": {
        "match": {
          "title.synonym": {
            "query": "wlh",
            "operator": "and"
          }
        }
      },
      "aggs": {
        "wlhAggs": {
          "terms": {
            "field": "title.synonym"
          }
        },
        "wlhFilter": {
          "filter": {
            "term": {
              "title": "wlh"
            }
          }
        }
      }
    }
    

    输出:

    {
      "aggregations": {
        "wlhAggs": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": "wellwell",
              "doc_count": 2
            },
            {
              "key": "else",
              "doc_count": 1
            },
            {
              "key": "other",
              "doc_count": 1
            },
            {
              "key": "smth",
              "doc_count": 1
            },
            {
              "key": "stuff",
              "doc_count": 1
            }
          ]
        },
        "wlhFilter": {
          "doc_count": 1
        }
      }
    }
    

    希望这有帮助!!

        2
  •  2
  •   nlv    7 年前

    • 我创建了一个单独的字段,使用同义词分析器,如下所示 反对使用属性字段(mainfield.property)。
    • 最重要的问题是我的同义词被压缩了!我 例如,英国英语=>英国。将其更改为 british,english,uk解决了我的问题,过滤器聚合是 返回正确数量的文档。

    希望这能帮助别人,或者至少指向正确的方向。

    编辑: 哦,上帝赞美文件!我完全修复了过滤器的问题聚合(链接 here ). 在过滤器配置中,我指定了查询的匹配类型,它成功了!结果是这样的:

    "aggs" : {
        "messages" : {
          "filters" : {
            "filters" : {
              "status" :   { "match" : { "cats.saurus" : "monarch"   }},
              "country" : { "match" : { "cats.saurus" : "british" }}
            }
          }
        }
      }