如何在query_string搜索中汇总匹配的词?

How to aggregate matched terms in a query_string search?

提问人:Sandy 提问时间:1/13/2023 最后编辑:Sandy 更新时间:1/16/2023 访问量:102

问:

我希望在字典的嵌套列表中搜索通配符术语,然后获取术语列表及其按匹配通配符分组的 uuid。

我的索引中有以下映射:

"mappings": {
    "properties": {
        "uuid": {
            "type": "keyword"
        },
        "urls": {
            "type": "nested",
            "properties": {
                "url": {
                    "type": "keyword"
                },
                "is_visited": {
                    "type": "boolean"
                }
            }
        }           
    }
}

还有很多数据,比如:

{
    "uuid":"afa9ac03-0723-4d66-ae18-08a51e2973bd"
    "urls": [
        {
            "is_visited": true,
            "url": "https://www.google.com"
        },
        {
            "is_visited": false,
            "url": "https://www.facebook.com"
        },
        {
            "is_visited": true,
            "url": "https://www.twitter.com"
        },              
    ]
},
{
    "uuid":"4a1c695d-756b-4d9d-b3a0-cf524d955884"
    "urls": [
        {
            "is_visited": true,
            "url": "https://www.stackoverflow.com"
        },
        {
            "is_visited": false,
            "url": "https://www.facebook.com"
        },
        {
            "is_visited": false,
            "url": "https://drive.google.com"
        },
        {
            "is_visited": false,
            "url": "https://maps.google.com"
        },                      
    ]
}
...

我希望通过通配符进行搜索并获得如下内容:"*google.com OR *twitter.com"

"hits": [
    "*google.com": [
        {
            "uuid": "4a1c695d-756b-4d9d-b3a0-cf524d955884",
            "_source": {
                "is_visited": false,
                "url": "https://drive.google.com"
            }
        },
        {
            "id": "4a1c695d-756b-4d9d-b3a0-cf524d955884",
            "_source": {
                "is_visited": false,
                "url": "https://maps.google.com"
            }
        },
        {
            "uuid":"afa9ac03-0723-4d66-ae18-08a51e2973bd",
            "_source": {
                "is_visited": true,
                "url": "https://www.google.com"
            }
        }
    ]
    "*twitter.com": [
        {
            "uuid":"afa9ac03-0723-4d66-ae18-08a51e2973bd",
            "_source": {
                "is_visited": true,
                "url": "https://www.twitter.com"
            },  
        },
    ]
]

这是我的(python)搜索查询:

body = {
  #"_source": False,
  "size": 100,
  "query": {
        "nested": {
            "path": "urls",
            "query":{
                "query_string":{
                    "query": f"urls.url:{urlToSearch}",
                }
            }
            ,"inner_hits": {
                "size":100 # returns top 100 results
            }
        }
    }
}

但它会为每个匹配的术语返回一个命中,而不是将它们聚合到类似于我想要得到的列表中。

编辑这是我的设置和映射:

{
    "settings": {
        "analysis": {
            "char_filter": {
                "my_filter": {
                    "type": "mapping",
                    "mappings": [
                        "- => _",
                    ]
                },
            },
            "analyzer": {
                "my_analyzer": {
                    "tokenizer": "standard",
                    "char_filter": [
                        "my_filter"
                    ],
                    "filter": [
                        "lowercase",
                    ]
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "uuid": {
                "type": "keyword"
            },
            "urls": {
                "type": "nested",
                "properties": {
                    "url": {
                        "type": "keyword"
                    },
                    "is_visited": {
                        "type": "boolean"
                    }
                }
            }           
        }
    }
}
Elasticsearch elasticsearch-aggregation elasticsearch-dsl

评论


答:

1赞 rabbitbr 1/13/2023 #1

Elasticsearch 不会像您设置查询那样提供您想要的输出。 此方案是聚合。我的建议是应用嵌套查询并对结果使用聚合。

注意点通配符查询

避免以 * 或 ?开头的模式。这可以增加迭代次数 需要查找匹配的词和缓慢的搜索性能。

{
  "size": 0,
  "query": {
    "nested": {
      "path": "urls",
      "query": {
        "bool": {
          "should": [
            {
              "wildcard": {
                "urls.url": {
                  "value": "*google.com"
                }
              }
            },
            {
              "wildcard": {
                "urls.url": {
                  "value": "*twitter.com"
                }
              }
            }
          ]
        }
      }
    }
  },
  "aggs": {
    "agg_providers": {
      "nested": {
        "path": "urls"
      },
      "aggs": {
        "google.com": {
          "terms": {
            "field": "urls.url",
            "include": ".*google.com",
            "size": 10
          }
        },
        "twitter.com": {
          "terms": {
            "field": "urls.url",
            "include": ".*twitter.com",
            "size": 10
          }
        }
      }
    }
  }
}

结果:

"aggregations": {
    "agg_providers": {
      "doc_count": 7,
      "twitter.com": {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 0,
        "buckets": [
          {
            "key": "https://www.twitter.com",
            "doc_count": 1
          }
        ]
      },
      "google.com": {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 0,
        "buckets": [
          {
            "key": "https://drive.google.com",
            "doc_count": 1
          },
          {
            "key": "https://maps.google.com",
            "doc_count": 1
          },
          {
            "key": "https://www.google.com",
            "doc_count": 1
          }
        ]
      }
    }
  }

评论

0赞 Sandy 1/13/2023
谢谢你的回答。所以,我使用(例如。 因为我有动态关键字),但它不起作用。它甚至不适用于您的查询,它会返回没有聚合的 json 结果。query_search"*google.com OR *twitter.com"
0赞 rabbitbr 1/13/2023
可能有些事情你没有提到。我的查询适用于您提供的数据。您必须使用通配符查询。为什么我的查询不返回 aggs?
0赞 Sandy 1/16/2023
我使用索引映射和设置编辑了我的原始帖子。所以,我尝试了你的查询的通配符,但没有返回 aggs
0赞 rabbitbr 1/16/2023
我用你报告的映射做了一个新的测试,我可以看到aggs。也许你把 aggs 和命中混淆了,这些真的是空的。
0赞 Sandy 1/17/2023
我做了一个请求,结果与你的相似!我认为 python 库中存在错误或要传递的参数curl