关系型数据库的范式设计
- 范式
- 1NF-消除非主属性对键的部分函数依赖
- 2NF-消除非主要属性对键的传递函数依赖
- 3NF-消除主属性对键的传递函数依赖
- BCNF-主属性不依赖于主属性
概念
- 范式化设计的主要目标是 减少不必要的更新
- 副作用:查询缓慢,多表联查
- 范式化虽节省空间,但存储越来越便宜
ES反范式-嵌套对象
post my_movies/_doc/1{"title":"Speed","actors":[{"first_name":"keanu","last_name":"Reeves"},{"first_name":"Dennis","last_name":"Hopper"}]}// JSON格式呗处理成扁平式键值对的结构// 这个文档的存储:"title":"Speed""actors.first_name":["keanu","Dennis"]"actors.last_name":["Reeves","Hopper"]
nested Data Type
- 允许对象数组中的对象被独立索引
- nested文档会被保存在两个Lucene文档中,在查询时做join处理
- 每次更新,需要重新索引整个对象(包括根对象和嵌套对象)
put my_movies{"mappings":{"properties":{"actors":{"type":"nested","properties":{"first_name":{"type":"keyword"},"last_name":{"type":"keyword"}}},"title":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}}}// nested 查询post my_movie/_search{"query":{"bool":{"must":[{"match":{"title":"Speed"}},{"nested":{"path":"actors","query":{"bool":{"must":[{"match":{"actors.first_name":"Keanu"}}]}}}}]}}}
示例
PUT /test_spu{"mappings": {"properties": {"spu_name":{"type": "text","null_value": "null"},"skus":{"type": "nested","properties": {"sku_name":{"type":"text"}}}}}}
父子文档
ES提供类似关系型数据库的Join实现,可以维护父子关系
- 父文档和子文档是两个独立的文档
更新父文档无需重新索引子文档。子文档被添加、更新或者删除也不会影响到父文档和其他子文档
// 设置mappingput my_blogs{"mappings":{"properties":{"blog_comments_relation":{"type":"join","relations":{"blog":"comment" -- parent名称:child名称}}}}}// 索引父文档put my_blogs/_doc/blog1{"title":"ES牛逼","content":"bilibili","blog_comments_relation":{"name":"blog" -- 申明文档类型}}// 索引子文档put my_blogs/_doc/comment1?routing=blog1 -- 指定routing,确保和付文档索引到相同的分片,提高join性能{"comment":"说的好","username":"张傲霜","blog_comments_relation":{"name":"comment","parent":"blog1" -- 父文档id}}// 父查子//parent_id查询post my_blogs/_search{"query":{"parent_id":{"type":"comment","id":"blog1"}}}// has_parent查询post my_blogs/_search{"query":{"has_parent":{"parent_type":"blog","query":{"match":{"title": "java"}}}}}// 子查父post my_blogs/_search{"query":{"has_child":{"type":"comment","query":{"match":{"username":"jack"}}}}}// 访问子文档get my_blogs/_doc/comment1?routing=blog1// 更新子文档put my_blogs/_doc/comment1?routing=blog1{"comment":"java is best"}
示例
//创建索引PUT /test_spu{"mappings": {"properties": {"name":{"type": "text"},"relation":{"type": "join","relations":{"spu":"sku"}}}}}// 索引父文档
