文档式存储模式

文档式存储模式

  1. 文档式存储模式概念

文档式存储模式和键值存储模式具有一定的相似性,但其值一般为半结构化内容,需要通过某种半结构化标记语言来进行描述。例如通过JSON或XML等方式来组织其值,键值存储则一般不关心值的结构。不同的元组对应的文档结构可能完全不同。文档中还可能会嵌套文档,以及出现不定长的重复属性,因此文档式存储模式也是无法预先定义结构的。

 

  1. 文档式存储模式优点

和键值模式相比,文档式存储模式强调可以通过关键词查询文档内部的结构,而非值通过键来进行检索。此外,由于文档允许嵌套,因此可以将传统关系型数据库中需要Join查询的字段整合为一个文档,这种做法理论上会增加存储开销,但是会提高查询效率。在分布式系统中,Join查询的开销较大,以文档式存储的嵌套结构的又是更加明显。

 

  1. 嵌套对象和父子文档

资料来源(https://my.oschina.net/fusublog/blog/3062114)

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

PUT 

{

  "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 后,每一个嵌套对象都会被索引为一个 隐藏的独立文档 

 

在独立索引每一个嵌套对象后,对象中每个字段的相关性得以保留。我们查询时,也仅仅返回那些真正符合条件的文档。不仅如此,由于嵌套文档直接存储在文档内部,查询时嵌套文档和根文档联合成本很低,速度和单独存储几乎一样。

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

 

父子文档

父-子关系文档在实质上类似于nested model :允许将一个对象实体和另外一个对象实体关联起来。 而这两种类型的主要区别是:在nested objects文档中,所有对象都是在同一个文档中,而在父-子关系文档中,父对象和子对象都是完全独立的文档。

父-子关系的主要作用是允许把一个 type 的文档和另外一个 type 的文档关联起来,构成一对多的关系:一个父文档可以对应多个子文档 。与 nested objects 相比,父-子关系的主要优势有:

1、更新父文档时,不会重新索引子文档。

2、创建,修改或删除子文档时,不会影响父文档或其他子文档。这一点在这种场景下尤其有用:子文档数量较多,并且子文档创建和修改的频率高时。

3、子文档可以作为搜索结果独立返回。

Elasticsearch 维护了一个父文档和子文档的映射关系,得益于这个映射,父-子文档关联查询操作非常快。但是这个映射也对父-子文档关系有个限制条件:父文档和其所有子文档,都必须要存储在同一个分片中。

 

父-子文档ID映射存储在 Doc Values 中。当映射完全在内存中时, Doc Values 提供对映射的快速处理能力,另一方面当映射非常大时,可以通过溢出到磁盘提供足够的扩展能力。

 

当文档索引性能远比查询性能重要的时候,父子关系是非常有用的,但是它也是有巨大代价的。其查询速度会比同等的嵌套查询慢5到10倍

 

4、JSON

JSON是一种轻量级的数据交换语言。JSON最被熟知的应用之一,是作为JavaScript语言中的对象和数组。JSON也被用来在RESTFUL风格的Web接口中进行数据交换。

JSON的语法规则

JSON是一个标记符的序列。这套标记符包含六个构造字符、字符串、数字和三个字面名。JSON是一个序列化的对象或数组。

 

 

1. 六个构造字符:

 [ 左方括号 、 { 左大括号 、 ] 右方括号 、 } 右大括号  : 冒号 、 , 逗号

2.JSON的值:

JSON值可以是对象、数组、数字、字符串或者三个字面值 (false、null、true)中的一个。值中的字面值中的英文必须使用小 写。

 

2.1对象由花括号括起来的逗号分割的成员构成,成员是字符 串键和上文所述的值由逗号分割的键值对组成

如:

     {"name": "John Doe", "age": 18, "address": {"country" : "china", "zip-code": "10000"}}

 

2.2数组是由方括号括起来的一组值构成

如:

[3, 1, 4, 1, 5, 9, 2, 6]

 

2.3 字符串与C或者Java的字符串非常相似。字符串是由双 引号包围的任意数量Unicode字符的集合,使用反斜线转 义。一个字符(character)即一个单独的字符串(character string)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值