普通object类型
用冗余数据的方式来建模,其实用的就是object类型,来看一个数据1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22PUT /website/blogs/6
{
"title": "花无缺发表的一篇帖子",
"content": "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",
"tags": [ "投资", "理财" ],
"comments": [
{
"name": "小鱼儿",
"comment": "什么股票啊?推荐一下呗",
"age": 28,
"stars": 4,
"date": "2016-09-01"
},
{
"name": "黄药师",
"comment": "我喜欢投资房产,风,险大收益也大",
"age": 31,
"stars": 5,
"date": "2016-10-22"
}
]
}
就是一个帖子下的所有评论,这种类型的数据,就是object类型的,然后来做一个搜索
搜索案例
需求: 搜索被年龄是28岁的黄药师评论过的博客
1 | GET /website/blogs/_search |
返回值:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45{
"took": 21,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.8022683,
"hits": [
{
"_index": "website",
"_type": "blogs",
"_id": "6",
"_score": 1.8022683,
"_source": {
"title": "花无缺发表的一篇帖子",
"content": "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",
"tags": [
"投资",
"理财"
],
"comments": [
{
"name": "小鱼儿",
"comment": "什么股票啊?推荐一下呗",
"age": 28,
"stars": 4,
"date": "2016-09-01"
},
{
"name": "黄药师",
"comment": "我喜欢投资房产,风,险大收益也大",
"age": 31,
"stars": 5,
"date": "2016-10-22"
}
]
}
}
]
}
}
注意,我们在添加数据的时候,黄药师的年龄是31的,但是搜索的时候还是搜索出来了,这个结果就不准确了,在之前有写过object类型的底层存储是怎样的结构, 会将一个数组中的数据,进行扁平化, 我们上面这条数据在底层的存储可能就是这样的
1 | { |
所以,我们的查询就会查询到这个document,name=黄药师,age=28,正好符合
那么怎么来解决这种问题呢?
nested object类型
通过使用nested object就可以解决上面出现的问题
首先,需要修改mapping,把之前的index删掉,重新建1
DELETE /website
然后创建索引,手动设置mapping1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19PUT /website
{
"mappings": {
"blogs": {
"properties": {
"comments":{
"type": "nested",
"properties": {
"name": { "type": "string" },
"comment": { "type": "string" },
"age": { "type": "short" },
"stars": { "type": "short" },
"date": { "type": "date" }
}
}
}
}
}
}
就是把comments的类型设置为nested,然后里面再设置各个属性,创建完成之后把之前那个数据再加进去.
搜索案例
再次按之前的需求搜索,看一下请求1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35GET website/blogs/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "花无缺"
}
},
{
"nested": {
"path": "comments",
"query": {
"bool": {
"must": [
{
"match": {
"comments.name": "黄药师"
}
},
{
"match": {
"comments.age": "28"
}
}
]
}
}
}
}
]
}
}
}
首先,就是一个bool组合查询,查的是外层的数据,然后里面套了一个nested, 然后里面又是一个bool组合查询
返回值:1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
这样的话就是查询不到的了.
nested object底层数据结构
1 | { |
nested object的底层数据结构是这样的,所以搜 name=黄药师而且age=28 的就搜索不到了
补充
查询请求的时候,nested 里面可以加一个参数,是score_mode,作用是就是,如果搜索命中了多个nested document,如何将多个nested document的分数合并为一个分数.
默认是avg,也可以设置max min none