对象及Nested对象
内部对象边界搜索异常
PUT my_movies{"mappings" : {"properties" : {"actors" : {"properties" : {"first_name" : {"type" : "keyword"},"last_name" : {"type" : "keyword"}}},"title" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}}}}}POST my_movies/_doc/1{"title":"Speed","actors":[{"first_name":"Keanu","last_name":"Reeves"},{"first_name":"Dennis","last_name":"Hopper"}]}
POST my_movies/_search{"query": {"bool": {"must": [{"match": {"actors.first_name": "Keanu"}},{"match": {"actors.last_name": "Hopper"}}]}}}
为什么会搜索到不需要的结果?
- 存储时,内部对象的边界并没有考虑在内,JSON格式被处理成扁平式键值对的结构
- 当对多个字段进行查询时,导致了意外的搜索结果
-
Nested Dtat Type 解决方案
Nested 数据类型:允许对象数组中的对象被独立索引
- 使用 nested 和 properties 关键字,将所有 actors 索引到多个分隔的文档
在内部,Nested 文档会被保存在两个 Lucene 文档中,在查询时做 Join 处理
DELETE my_moviesPUT 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}}}}}}
POST my_movies/_doc/1{"title":"Speed","actors":[{"first_name":"Keanu","last_name":"Reeves"},{"first_name":"Dennis","last_name":"Hopper"}]}
查询
POST my_movies/_search{"query": {"bool": {"must": [{"match": {"title": "Speed"}},{"nested": {"path": "actors","query": {"bool": {"must": [{"match": {"actors.first_name": "Keanu"}},{"match": {"actors.last_name": "Hopper"}}]}}}}]}}}
聚合
POST my_movies/_search{"size": 0,"aggs": {"actors": {"nested": {"path": "actors"},"aggs": {"actor_name": {"terms": {"field": "actors.first_name","size": 10}}}}}}
文档的父子关系
Elasticsearch 提供了类似关系型数据库中的 Join 的实现。使用 Join 数据类型实现,可以通过维护 Parent / Child 的关系。从而分离两个对象。父文档和子文档是两个独立的文档,更新父文档无需重新索引子文档。
父子关系 Mapping 声明
```json
my_blogs:索引名称
blog_comments_relation:关联关系名称
blog:父文档名称
comment:子文档名称
PUT my_blogs { “mappings”: { “properties”: { “blog_comments_relation”: { “type”: “join”, “relations”: { “blog”: “comment” } }, “content”: { “type”: “text” }, “title”: { “type”: “keyword” } } } }
<a name="BCXZP"></a>## 索引父子文档```json# my_blogs:索引名称# blog1、blog2:文档idPUT my_blogs/_doc/blog1{"title":"Learning Elasticsearch","content":"learning ELK @ geektime","blog_comments_relation":{"name":"blog"}}PUT my_blogs/_doc/blog2{"title":"Learning Hadoop","content":"learning Hadoop","blog_comments_relation":{"name":"blog"}}
# my_blogs:索引名称# comment1、comment2、comment3:子文档id# blog1、blog2:父文档id,通过routing确保文档与父文档存储同一分片PUT my_blogs/_doc/comment1?routing=blog1{"comment":"I am learning ELK","username":"Jack","blog_comments_relation":{"name":"comment","parent":"blog1"}}PUT my_blogs/_doc/comment2?routing=blog2{"comment":"I like Hadoop!!!!!","username":"Jack","blog_comments_relation":{"name":"comment","parent":"blog2"}}PUT my_blogs/_doc/comment3?routing=blog2{"comment":"Hello Hadoop","username":"Bob","blog_comments_relation":{"name":"comment","parent":"blog2"}}
搜索父子文档
#根据父文档ID查看GET my_blogs/_doc/blog2# Parent Id 查询POST my_blogs/_search{"query": {"parent_id": {"type": "comment","id": "blog2"}}}# Has Child 查询,返回父文档POST my_blogs/_search{"query": {"has_child": {"type": "comment","query" : {"match": {"username" : "Jack"}}}}}# Has Parent 查询,返回相关的子文档POST my_blogs/_search{"query": {"has_parent": {"parent_type": "blog","query" : {"match": {"title" : "Learning Hadoop"}}}}}
更新子文档
PUT my_blogs/_doc/comment3?routing=blog2{"comment": "Hello Hadoop??","blog_comments_relation": {"name": "comment","parent": "blog2"}}
字段建模
如何进行字段建模
- Text
- 用于全文本字段,文本会被 Analyzer 分词
- 默认不支持聚合分析以及排序,需要设置 fielddata 为 true
- Keyword
- 用于 id,枚举以及不需要分词的文本。例如电话号码,email地址,手机号码,邮政编码,性别等
- 适用于 Filter (精准匹配),Sorting 和 Aggregations
设置多字段类型
数值类型:尽量选择贴近的类型。例如可以用 byte,就不要用 long。
- 枚举类型:设置为 keyword,即便是数字,也应该设置成 keyword,获得更好的性能。
-
检索
如不需要检索,排序和聚合分析:Enable 设置成 false。
- 如不需要检索,Index 设置成 false。
对需要检索的字段,可以通过如下配置,设定存储粒度:Index options / Norms:不需要归一化数据。
聚合以及排序
如不需要检索,排序和聚合分析:Enable 设置成 false。
- 如不需要排序或者聚合分析功能:Doc_values / fielddata 设置成 false。
更新频繁,聚合查询频繁的 keyword 类型的字段:推荐将 eager_global_ordinals 设置为 true。
额外的存储
是否需要专门存储当前字段数据
- Store 设置成 true,可以存储该字段的原始内容
- 一般结合 _source 的 enabled 为 false 的时候使用
- Disable _source:节约磁盘,适用于指标型数据
- 一般建议先考虑增加压缩比
- 无法看到 _source 字段,无法做 Relndex,无法做 Update。
