概述
继续跟中华石杉老师学习ES,第58篇
课程地址: https://www.roncoo.com/view/55
官网
Nested datatype:戳这里
Object datatype:戳这里
示例
Object datatype
让ES自动创建索引,插入一条数据
#让ES自动创建索引,插入一条数据 PUT /website/blogs/1 { "title": "花无缺发表的一篇帖子", "content": "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。", "tags": [ "投资", "理财" ], "comments": [ { "name": "小鱼儿", "comment": "什么股票啊?推荐一下呗", "age": 28, "stars": 4, "date": "2016-09-01" }, { "name": "黄药师", "comment": "我喜欢投资房产,风,险大收益也大", "age": 31, "stars": 5, "date": "2016-10-22" } ] }
查看mapping
GET /website/_mapping/blogs/
返回:
{ "website": { "mappings": { "blogs": { "properties": { "comments": { "properties": { "age": { "type": "long" }, "comment": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "date": { "type": "date" }, "name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "stars": { "type": "long" } } }, "content": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "tags": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "title": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
需求: 被年龄是28岁的黄药师评论过的博客
#被年龄是28岁的黄药师评论过的博客 GET /website/blogs/_search { "query": { "bool": { "must": [ { "match": { "comments.name": "黄药师" } }, { "match": { "comments.age": 28 } } ] } } }
返回:
查询结果不对原因分析
官方文档: 戳这里
归根到底 还是object类型数据结构的底层存储导致的查询不正确
{ "title": [ "花无缺", "发表", "一篇", "帖子" ], "content": [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ], "tags": [ "投资", "理财" ], "comments.name": [ "小鱼儿", "黄药师" ], "comments.comment": [ "什么", "股票", "推荐", "我", "喜欢", "投资", "房产", "风险", "收益", "大" ], "comments.age": [ 28, 31 ], "comments.stars": [ 4, 5 ], "comments.date": [ 2016-09-01, 2016-10-22 ] }
object类型底层数据结构,会将一个json数组中的数据,进行扁平化
所以,直接命中了这个document,name=黄药师,age=28,在范围之内,正好符合,所以被查询出来了。
Nested datatype
解决object查询不对的问题
引入nested object类型,来解决object类型底层数据结构导致的问题
修改mapping,将comments的类型从object设置为nested
修改mapping,将comments的类型从object设置为nested
DELETE website PUT /website { "mappings": { "blogs": { "properties": { "comments": { "type": "nested", "properties": { "name": { "type": "text" }, "comment": { "type": "text" }, "age": { "type": "short" }, "stars": { "type": "short" }, "date": { "type": "date" } } } } } } }
写入数据
PUT /website/blogs/1 { "title": "花无缺发表的一篇帖子", "content": "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。", "tags": [ "投资", "理财" ], "comments": [ { "name": "小鱼儿", "comment": "什么股票啊?推荐一下呗", "age": 28, "stars": 4, "date": "2016-09-01" }, { "name": "黄药师", "comment": "我喜欢投资房产,风,险大收益也大", "age": 31, "stars": 5, "date": "2016-10-22" } ] }
查看mapping
#查看mapping GET /website/_mapping/blogs/
返回:
{ "website": { "mappings": { "blogs": { "properties": { "comments": { "type": "nested", "properties": { "age": { "type": "short" }, "comment": { "type": "text" }, "date": { "type": "date" }, "name": { "type": "text" }, "stars": { "type": "short" } } }, "content": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "tags": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "title": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
nested object 存储形式
这样的话,nested object 存储如下:
{ "comments.name": [ "小鱼儿" ], "comments.comment": [ "什么", "股票", "推荐" ], "comments.age": [ 28 ], "comments.stars": [ 4 ], "comments.date": [ 2014-09-01 ] } { "comments.name": [ "黄药师" ], "comments.comment": [ "我", "喜欢", "投资", "房产", "风险", "收益", "大" ], "comments.age": [ 31 ], "comments.stars": [ 5 ], "comments.date": [ 2014-10-22 ] } { "title": [ "花无缺", "发表", "一篇", "帖子" ], "body": [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ], "tags": [ "投资", "理财" ] }
再次查询
GET /website/blogs/_search { "query": { "bool": { "must": [ { "match": { "title": "花无缺" } }, { "nested": { "path": "comments", "query": { "bool": { "must": [ { "match": { "comments.name": "黄药师" } }, { "match": { "comments.age": 28 } } ] } } } } ] } } }
改成31的呢
score_mode
score_mode:max,min,avg,none,默认是avg
如果搜索命中了多个nested document,如何把多个nested document的分数合并为一个分数
limits on nested mappings and objects