0

我正在寻找一个查询,它将返回给定值列表中文档中缺少的值。例如,文档中有一个国家字段,其值为 USA、Dubai、Singapore、Japan。现在我想告诉弹性搜索,我正在给你国家列表(美国、迪拜、俄罗斯),你给我的输出告诉我俄罗斯不属于任何文件。这可能吗?

4

1 回答 1

1

您需要执行如下查询,仅选择包含美国、迪拜和俄罗斯的文档,然后汇总这些country值。

{
  "size": 0,
  "query": {
    "terms": {
      "country": [
        "USA",
        "Dubai",
        "Russia"
      ]
    }
  },
  "aggs": {
    "countries": {
      "terms": {
        "field": "country"
      }
    }
  }
}

在结果中,您将获得所有存在的国家(即美国和迪拜)的桶,而没有俄罗斯的桶。

然后,您可以通过将输入数组与从聚合结果中获得的数组相减来进行简单的集合算术运算,您将找到所需的内容,即:

[USA, Dubai, Russia] - [USA, Dubai] = [Russia]

更新:如果您想在一个国家/地区完成上述所有操作,您可以利用scripted_metric聚合

map_script将为分片上的每个文档运行并将所有当前国家/地区存储在临时变量state.countries中。

reduce_script将在协调节点上运行并接收所有分片的结果。该脚本只是比较params.countries数组中存在的国家/地区,并且仅输出不存在的国家/地区。

POST country/_search
{
  "size": 0,
  "query": {
    "terms": {
      "country": [
        "USA",
        "Dubai",
        "Russia"
      ]
    }
  },
  "aggs": {
    "missing_countries": {
      "scripted_metric": {
        "init_script": "state.countries = [:]",
        "map_script": """
          def country = doc['country.keyword'].value;
          if (!state.countries.containsKey(country)) {
            state.countries[country] = 0;
          }
          state.countries[country]++;
        """,
        "combine_script": """
          return state.countries;
        """,
        "reduce_script": """
          // gather all present countries
          def countries = new HashSet(); 
          for (state in states) {
            countries.addAll(state.keySet());
          }
          // figure out which country in params is not present in countries
          def missing = [];
          for (country in params.countries) {
            if (!countries.contains(country)) {
              missing.add(country);
            }
          }
          return missing;
        """,
        "params": {
          "countries": ["USA", "Dubai", "Russia"]
        }
      }
    }
  }
}

在这种情况下,输出将是

  "aggregations" : {
    "missing_countries" : {
      "value" : [
        "Russia"
      ]
    }
  }
于 2020-11-05T13:29:14.710 回答