nested类型是专门为支持数组对象索引的数据类型服务的,在某种程度上可以相互独立查询。
tip:当接收大量的键值对或者key的类型比较分散,你可以考虑为每个key-value建立自己的nested类型的document。相反,也可以考虑使用flattened数据类型,这种数据类型可以将整个对象映射为单个字段,并且可以在其content上进行一些简单的搜索。

对象数组是如何打平的

Elasticsearch并没有内部对象的概念。因此,它将对象的层次打平为一个简单的name-value的列表。例如,如下的文档:

  1. PUT my-index-000001/_doc/1
  2. {
  3. "group" : "fans",
  4. "user" : [
  5. {
  6. "first" : "John",
  7. "last" : "Smith"
  8. },
  9. {
  10. "first" : "Alice",
  11. "last" : "White"
  12. }
  13. ]
  14. }

①:user是字段作为object字段类型动态添加的。

在系统内部以前的文档会转换为类似下面的数据结构:

  1. {
  2. "group" : "fans",
  3. "user.first" : [ "alice", "john" ],
  4. "user.last" : [ "smith", "white" ]
  5. }

user.first和user.last字段会被打平为数组字段,并且会丢失alice和white之间的关系。这个文档就会错误的匹配到alice 和 smith的查询:

  1. GET my-index-000001/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. { "match": { "user.first": "Alice" }},
  7. { "match": { "user.last": "Smith" }}
  8. ]
  9. }
  10. }
  11. }

对数组类型的对象使用nested类型

如果你需要索引对象数组并且保持数组中每个对象独立,使用nested来代替object数据类型。

在内部,nested对象会将数组中的每个对象作为单独的隐藏的文档来索引,意味着每个nested对象可以使用nested独立查询:

  1. PUT my-index-000001
  2. {
  3. "mappings": {
  4. "properties": {
  5. "user": {
  6. "type": "nested"
  7. }
  8. }
  9. }
  10. }
  11. PUT my-index-000001/_doc/1
  12. {
  13. "group" : "fans",
  14. "user" : [
  15. {
  16. "first" : "John",
  17. "last" : "Smith"
  18. },
  19. {
  20. "first" : "Alice",
  21. "last" : "White"
  22. }
  23. ]
  24. }
  25. GET my-index-000001/_search
  26. {
  27. "query": {
  28. "nested": {
  29. "path": "user",
  30. "query": {
  31. "bool": {
  32. "must": [
  33. { "match": { "user.first": "Alice" }},
  34. { "match": { "user.last": "Smith" }}
  35. ]
  36. }
  37. }
  38. }
  39. }
  40. }
  41. GET my-index-000001/_search
  42. {
  43. "query": {
  44. "nested": {
  45. "path": "user",
  46. "query": {
  47. "bool": {
  48. "must": [
  49. { "match": { "user.first": "Alice" }},
  50. { "match": { "user.last": "White" }}
  51. ]
  52. }
  53. },
  54. "inner_hits": {
  55. "highlight": {
  56. "fields": {
  57. "user.first": {}
  58. }
  59. }
  60. }
  61. }
  62. }
  63. }

①:user字段映射为nested类型而不是object类型
②:此查询不会匹配任何数据,应为alice和smith没有在同一个nested对象中。
③:此查询会匹配到数据,因为alice和white在同一个nested对象中。
④:inner_hits允许我们高亮匹配的nested文档。

与nested文档交互

nested文档可以:

重要:因为nested是被分开索引的,因此他们只能被nsted query、ested/reverse_nested aggregations, or nested inner hits查询到。
例如,nested文档内的字符串字段,index_options设为offsets,使得在高亮时允许use of the postings。这些offsets在主要的高亮阶段将不可用。反而,高亮需要通过nested inner hits来执行。同样的考虑也使用当在搜索中通过docvalue_fields 或者 stored_fields加载字段时。

nested字段参数