在我之前的文章 “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 文档被查找到。