在我之前的文章 “Elasticsearch: object 及 nested 数据类型” 对 nested 数据类型做了一个比较详细的介绍。在实际运用中,你在构建查询时肯定会遇到一些问题。根据官方文档介绍,nested 类型字段在躲藏数组中索引其每个项目,这答应独立于索引文档查找这些项目。今日我带来一个问题:问如何取得一个文档,其整个 item 列表有必要与一个子句匹配。 让我举个比如让你更清楚。

我有一个 item 字段设置为 nested的索引。 我索引了两个文档,其间一个一切项目的 status 都为 active,另一个则不满是。


1.  PUT nested_index
2.  {
3.    "mappings": {
4.      "properties": {
5.        "description": {
6.          "type": "text"
7.        },
8.        "item": {
9.          "type": "nested",
10.          "properties": {
11.            "value": {
12.              "type": "text"
13.            },
14.            "status": {
15.              "type": "keyword"
16.            }
17.          }
18.        }
19.      }
20.    }
21.  }

1.  POST nested_index/_doc
2.  {
3.    "description": "nested A",
4.    "item": [
5.      {
6.        "value": "a",
7.        "status": "active"
8.      },
9.      {
10.        "value": "ab",
11.        "status": "active"
12.      }
13.    ]
14.  }
16.  POST nested_index/_doc
17.  {
18.    "description": "nested B",
19.    "item": [
20.      {
21.        "value": "b",
22.        "status": "inactive"
23.      },
24.      {
25.        "value": "bc",
26.        "status": "active"
27.      }
28.    ]
29.  }

如上所示,第一个文档里的 status 都是 active 的状况,而第二个文档的其间一个 status 状况是 active,另外一个是 inactive 状况。

现在我们想要查询的问题是:查找到 status 都是 active 的文档。

或许你会想到运用如下的查询:


1.  GET nested_index/_search
2.  {
3.    "query": {
4.      "nested": {
5.        "path": "item",
6.        "query": {
7.          "term": {
8.            "item.status": {
9.              "value": "active"
10.            }
11.          }
12.        }
13.      }
14.    }
15.  }

上面指令查询的成果是:


1.  {
2.    "took": 1,
3.    "timed_out": false,
4.    "_shards": {
5.      "total": 1,
6.      "successful": 1,
7.      "skipped": 0,
8.      "failed": 0
9.    },
10.    "hits": {
11.      "total": {
12.        "value": 2,
13.        "relation": "eq"
14.      },
15.      "max_score": 0.35667494,
16.      "hits": [
17.        {
18.          "_index": "nested_index",
19.          "_id": "xRoaRIYB2XodIZsbUfzi",
20.          "_score": 0.35667494,
21.          "_source": {
22.            "description": "nested A",
23.            "item": [
24.              {
25.                "value": "a",
26.                "status": "active"
27.              },
28.              {
29.                "value": "ab",
30.                "status": "active"
31.              }
32.            ]
33.          }
34.        },
35.        {
36.          "_index": "nested_index",
37.          "_id": "xhoaRIYB2XodIZsbWvzm",
38.          "_score": 0.35667494,
39.          "_source": {
40.            "description": "nested B",
41.            "item": [
42.              {
43.                "value": "b",
44.                "status": "inactive"
45.              },
46.              {
47.                "value": "bc",
48.                "status": "active"
49.              }
50.            ]
51.          }
52.        }
53.      ]
54.    }
55.  }

明显两个文档都被查询到了。这个不是我们想要的成果。

处理它的方法是运用两个 must_not 子句。 最里面的 must_not 子句将过滤文档 A,由于一切项目都具有 active状况。 最外层的 must_not 将回转操作,迄今为止省掉的文档 A 将可用,而文档 B 将不可用且不会出现在呼应中。


1.  GET nested_index/_search
2.  {
3.    "query": {
4.      "bool": {
5.        "must_not": [
6.          {
7.            "nested": {
8.              "path": "item",
9.              "query": {
10.                "bool": {
11.                  "must_not": [
12.                    {
13.                      "term": {
14.                        "item.status": {
15.                          "value": "active"
16.                        }
17.                      }
18.                    }
19.                  ]
20.                }
21.              }
22.            }
23.          }
24.        ]
25.      }
26.    }
27.  }

上面的指令成果为:


1.  {
2.    "took": 2,
3.    "timed_out": false,
4.    "_shards": {
5.      "total": 1,
6.      "successful": 1,
7.      "skipped": 0,
8.      "failed": 0
9.    },
10.    "hits": {
11.      "total": {
12.        "value": 1,
13.        "relation": "eq"
14.      },
15.      "max_score": 0,
16.      "hits": [
17.        {
18.          "_index": "nested_index",
19.          "_id": "xRoaRIYB2XodIZsbUfzi",
20.          "_score": 0,
21.          "_source": {
22.            "description": "nested A",
23.            "item": [
24.              {
25.                "value": "a",
26.                "status": "active"
27.              },
28.              {
29.                "value": "ab",
30.                "status": "active"
31.              }
32.            ]
33.          }
34.        }
35.      ]
36.    }
37.  }

这次明显只要 nested A 文档被查找到。