博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Elasticsearch: 权威指南 » 数据建模 » 嵌套对象
阅读量:6234 次
发布时间:2019-06-22

本文共 4274 字,大约阅读时间需要 14 分钟。

hot3.png

由于在 Elasticsearch 中单个文档的增删改都是原子性操作,那么将相关实体数据都存储在同一文档中也就理所当然。 比如说,我们可以将订单及其明细数据存储在一个文档中。又比如,我们可以将一篇博客文章的评论以一个 comments 数组的形式和博客文章放在一起:

PUT /my_index/blogpost/1{  "title": "Nest eggs",  "body":  "Making your money work...",  "tags":  [ "cash", "shares" ],  "comments": [     {      "name":    "John Smith",      "comment": "Great article",      "age":     28,      "stars":   4,      "date":    "2014-09-01"    },    {      "name":    "Alice White",      "comment": "More like this please",      "age":     31,      "stars":   5,      "date":    "2014-10-22"    }  ]}

如果我们依赖,那么 comments 字段会自动映射为 object 类型。

由于所有的信息都在一个文档中,当我们查询时就没有必要去联合文章和评论文档,查询效率就很高。

但是当我们使用如下查询时,上面的文档也会被当做是符合条件的结果:

GET /_search{  "query": {    "bool": {      "must": [        { "match": { "name": "Alice" }},        { "match": { "age":  28      }}       ]    }  }}

Alice实际是31岁,不是28!

正如我们在  中讨论的一样,出现上面这种问题的原因是 JSON 格式的文档被处理成如下的扁平式键值对的结构。

{  "title":            [ eggs, nest ],  "body":             [ making, money, work, your ],  "tags":             [ cash, shares ],  "comments.name":    [ alice, john, smith, white ],  "comments.comment": [ article, great, like, more, please, this ],  "comments.age":     [ 28, 31 ],  "comments.stars":   [ 4, 5 ],  "comments.date":    [ 2014-09-01, 2014-10-22 ]}

Alice 和 31 、 John 和 2014-09-01 之间的相关性信息不再存在。虽然 object 类型 (参见 ) 在存储 单一对象 时非常有用,但对于对象数组的搜索而言,毫无用处。

嵌套对象 就是来解决这个问题的。将 comments 字段类型设置为 nested 而不是 object 后,每一个嵌套对象都会被索引为一个 隐藏的独立文档 ,举例如下:

{   "comments.name":    [ john, smith ],  "comments.comment": [ article, great ],  "comments.age":     [ 28 ],  "comments.stars":   [ 4 ],  "comments.date":    [ 2014-09-01 ]}{   "comments.name":    [ alice, white ],  "comments.comment": [ like, more, please, this ],  "comments.age":     [ 31 ],  "comments.stars":   [ 5 ],  "comments.date":    [ 2014-10-22 ]}{   "title":            [ eggs, nest ],  "body":             [ making, money, work, your ],  "tags":             [ cash, shares ]}

第一个 嵌套文档

第二个 嵌套文档

根文档 或者也可称为父文档

在独立索引每一个嵌套对象后,对象中每个字段的相关性得以保留。我们查询时,也仅仅返回那些真正符合条件的文档。

不仅如此,由于嵌套文档直接存储在文档内部,查询时嵌套文档和根文档联合成本很低,速度和单独存储几乎一样。

嵌套文档是隐藏存储的,我们不能直接获取。如果要增删改一个嵌套对象,我们必须把整个文档重新索引才可以。值得注意的是,查询的时候返回的是整个文档,而不是嵌套文档本身。

 

https://www.elastic.co/guide/cn/elasticsearch/guide/current/nested-objects.html#nested-objects

 

由于嵌套对象 被索引在独立隐藏的文档中,我们无法直接查询它们。 相应地,我们必须使用 去获取它们:

GET /my_index/blogpost/_search{  "query": {    "bool": {      "must": [        {          "match": {            "title": "eggs"           }        },        {          "nested": {            "path": "comments",             "query": {              "bool": {                "must": [                   {                    "match": {                      "comments.name": "john"                    }                  },                  {                    "match": {                      "comments.age": 28                    }                  }                ]              }            }          }        }      ]}}}

title 子句是查询根文档的。

nested 子句作用于嵌套字段 comments 。在此查询中,既不能查询根文档字段,也不能查询其他嵌套文档。

comments.name 和 comments.age 子句操作在同一个嵌套文档中。

提示

nested 字段可以包含其他的 nested 字段。同样地,nested 查询也可以包含其他的 nested 查询。而嵌套的层次会按照你所期待的被应用。

nested 查询肯定可以匹配到多个嵌套的文档。每一个匹配的嵌套文档都有自己的相关度得分,但是这众多的分数最终需要汇聚为可供根文档使用的一个分数。

默认情况下,根文档的分数是这些嵌套文档分数的平均值。可以通过设置 score_mode 参数来控制这个得分策略,相关策略有 avg (平均值), max (最大值), sum (加和) 和 none (直接返回 1.0 常数值分数)。

GET /my_index/blogpost/_search{  "query": {    "bool": {      "must": [        {          "match": {            "title": "eggs"          }        },        {          "nested": {            "path": "comments",            "score_mode": "max",             "query": {              "bool": {                "must": [                  {                    "match": {                      "comments.name": "john"                    }                  },                  {                    "match": {                      "comments.age": 28                    }                  }                ]              }            }          }        }      ]    }  }}

返回最优匹配嵌套文档的 _score 给根文档使用。

注意

如果 nested 查询放在一个布尔查询的 filter 子句中,其表现就像一个 nested 查询,只是 score_mode 参数不再生效。因为它被用于不打分的查询中 — 只是符合或不符合条件,不必打分 — 那么 score_mode 就没有任何意义,因为根本就没有要打分的地方。

 

https://www.elastic.co/guide/cn/elasticsearch/guide/current/nested-query.html

转载于:https://my.oschina.net/xiaominmin/blog/1788596

你可能感兴趣的文章
avro简介
查看>>
修改tomcat默认启动的工程
查看>>
Eclipse/MyEclipse注释模板和格式化模板的使用
查看>>
Putty 登录系统慢
查看>>
用组策略统一域中所有客户端桌面
查看>>
Mem系列函数与Str系列函数总结 (四) memchr 与 stchr
查看>>
考试系统Kaldin
查看>>
比较两个相同的对象
查看>>
excel 两列数据怎么把组合的可能全部做出来?
查看>>
Java学习基本步骤
查看>>
一个杀不死的小强,kill进程无效的原因
查看>>
迎娶大数据-【软件和信息服务】2013.2
查看>>
关于面向对象编程
查看>>
NFS详解
查看>>
如何清理 C 盘空间
查看>>
Redis的复制
查看>>
Nagios整合pnp绘制性能分析图表
查看>>
用word-wrap来解决固定大小ul下的每条li中内容太多时不自动换行问题
查看>>
学生QQ群发展壮大了
查看>>
使用 CXF 做 webservice 简单例子
查看>>