查询文档 & 基本操作
为了方便学习, 本节中所有示例沿用上节的索引
按照ID单个
1
|
GET class_ 1 /_doc/ 1 |
查询结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{ "_index" : "class_1" , "_type" : "_doc" , "_id" : "1" , "_version" : 4 , "_seq_no" : 4 , "_primary_term" : 3 , "found" : true , "_source" : { "name" : "l" , "num" : 6 } } |
按照ID批量
1
2
3
4
|
GET class_ 1 /_mget { "ids" :[ 1 , 2 , 3 ] } |
返回:
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
|
{ "docs" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "1" , "_version" : 4 , "_seq_no" : 4 , "_primary_term" : 3 , "found" : true , "_source" : { "name" : "l" , "num" : 6 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "2" , "found" : false }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "3" , "_version" : 3 , "_seq_no" : 10 , "_primary_term" : 4 , "found" : true , "_source" : { "num" : 9 , "name" : "e" , "age" : 9 , "desc" : [ "hhhh" ] } } ] } |
查询文档是否存在 & 通过id判断
1
|
HEAD class_ 1 /_doc/ 1 |
返回:
200 - OK
HEAD class_1/_doc/1000
返回:
404 - Not Found
查询部分字段内容
1
|
GET class_ 1 /_doc/ 1 ?_source_includes=name |
返回:
1
2
3
4
5
6
7
8
9
10
11
12
|
{ "_index" : "class_1" , "_type" : "_doc" , "_id" : "1" , "_version" : 4 , "_seq_no" : 4 , "_primary_term" : 3 , "found" : true , "_source" : { "name" : "l" } } |
可以看到只返回了name
字段, 以上是一个基本的操作,下面给大家讲下条件查询~
查询文档 & 条件查询
查询的复杂度取决于它附加的条件约束,跟我们写sql
一样。下面就带大家一步一步看一下ES
中如何进行条件查询~
不附加任何条件
1
|
GET class_ 1 /_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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
{ "took" : 15 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 8 , "relation" : "eq" }, "max_score" : 1.0 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "h2Fg-4UBECmbBdQA6VLg" , "_score" : 1.0 , "_source" : { "name" : "b" , "num" : 6 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "iGFt-4UBECmbBdQAnVJe" , "_score" : 1.0 , "_source" : { "name" : "g" , "age" : 8 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "iWFt-4UBECmbBdQAnVJg" , "_score" : 1.0 , "_source" : { "name" : "h" , "age" : 9 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "imFt-4UBECmbBdQAnVJg" , "_score" : 1.0 , "_source" : { "name" : "i" , "age" : 10 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "3" , "_score" : 1.0 , "_source" : { "num" : 9 , "name" : "e" , "age" : 9 , "desc" : [ "hhhh" ] } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "4" , "_score" : 1.0 , "_source" : { "name" : "f" , "age" : 10 , "num" : 10 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "RWlfBIUBDuA8yW5cu9wu" , "_score" : 1.0 , "_source" : { "name" : "一年级" , "num" : 20 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "1" , "_score" : 1.0 , "_source" : { "name" : "l" , "num" : 6 } } ] } } |
可以看到索引class_1
中的所有数据都是上节添加的。这里提一下,我们也可以添加多个索引一起查,然后返回,用,逗号
隔开就可以了
1
|
GET class_ 1 ,class_ 2 ,class_ 3 /_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
|
{ "took" : 7 , "timed_out" : false , "_shards" : { "total" : 5 , "successful" : 5 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 9 , "relation" : "eq" }, "max_score" : 1.0 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "h2Fg-4UBECmbBdQA6VLg" , "_score" : 1.0 , "_source" : { "name" : "b" , "num" : 6 } }, { "_index" : "class_2" , "_type" : "_doc" , "_id" : "RWlfBIUBDuA8yW5cu9wu" , "_score" : 1.0 , "_source" : { "name" : "一年级" , "num" : 20 } }, .... ] } } |
可以看到返回了索引class_2
中的数据,并且合并到了一起。
相关字段解释
有的小伙伴可能对返回的字段有点陌生,这里给大家统一解释一下:
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
|
{ "took" : "查询操作耗时,单位毫秒" , "timed_out" : "是否超时" , "_shards" :{ "total" : "分片总数" , "successful" : "执行成功分片数" , "skipped" : "执行忽略分片数" , "failed" : "执行失败分片数" }, "hits" :{ "total" :{ "value" : "条件查询命中数" , "relation" : "计数规则(eq计数准确/gte计数不准确)" }, "max_score" : "最大匹配度分值" , "hits" :[ { "_index" : "命中结果索引" , "_id" : "命中结果ID" , "_score" : "命中结果分数" , "_source" : "命中结果原文档信息" } ] } } |
下面我们看下带条件的查询~
基础分页查询
基本语法: es
中通过参数size
和from
来进行基础分页
的控制
-
from
:指定跳过
多少条数据 -
size
:指定返回
多少条数据
下面看下示例:
url参数
1
|
GET class_ 1 /_search?from= 2 &size= 2 |
返回:
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
|
{ "took" : 5 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 8 , "relation" : "eq" }, "max_score" : 1.0 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "iWFt-4UBECmbBdQAnVJg" , "_score" : 1.0 , "_source" : { "name" : "h" , "age" : 9 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "imFt-4UBECmbBdQAnVJg" , "_score" : 1.0 , "_source" : { "name" : "i" , "age" : 10 } } ] } } |
body 参数
1
2
3
4
5
|
GET class_ 1 /_search { "from" : 2 , "size" : 2 } |
返回结果和上面是一样的~
单字段全文索引查询
这个大家应该不陌生,前面几节都见过。使用query.match
进行查询,match
适用与对单个字段基于全文索引进行数据检索。对于全文字段,match
使用特定的分词
进行全文检索。而对于那些精确值,match
同样可以进行精确匹配,match
查询短语时,会对短语进行分词,再针对每个词条进行全文检索。
1
2
3
4
5
6
7
8
|
GET class_ 1 /_search { "query" : { "match" : { "name" : "i" } } } |
返回:
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
|
{ "took" : 4 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 1 , "relation" : "eq" }, "max_score" : 1.3862942 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "imFt-4UBECmbBdQAnVJg" , "_score" : 1.3862942 , "_source" : { "name" : "i" , "age" : 10 } } ] } } |
单字段不分词查询
使用query.match_phrase
进行查询, 它与match
的区别就是不进行分词,干说,可能有点抽象,下面我们通过一个例子给大家分清楚:
先造点数据进去:
1
2
3
4
5
6
7
|
PUT class_ 1 /_bulk { "create" :{ } } { "name" : "I eat apple so haochi1~" , "num" : 1 } { "create" :{ } } { "name" : "I eat apple so zhen haochi2~" , "num" : 1 } { "create" :{ } } { "name" : "I eat apple so haochi3~" , "num" : 1 } |
假设有这么几个句子,现在我有一个需求我要把I eat apple so zhen haochi2~
这句话匹配出来
match分词结果
1
2
3
4
5
6
7
8
|
GET class_ 1 /_search { "query" : { "match" : { "name" : "apple so zhen" } } } |
返回:
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
46
47
48
49
|
{ "took" : 15 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 3 , "relation" : "eq" }, "max_score" : 2.2169428 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "cMfcCoYB090miyjed7YE" , "_score" : 2.2169428 , "_source" : { "name" : "I eat apple so zhen haochi2~" , "num" : 1 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "b8fcCoYB090miyjed7YE" , "_score" : 1.505254 , "_source" : { "name" : "I eat apple so haochi1~" , "num" : 1 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "ccfcCoYB090miyjed7YE" , "_score" : 1.505254 , "_source" : { "name" : "I eat apple so haochi3~" , "num" : 1 } } ] } } |
从结果来看,刚刚的几句话都被查出来了,但是结果并大符合预期。从score
来看,"_score" : 2.2169428
得分最高,排在了第一,语句是I eat apple so zhen haochi2~
,说明匹配度最高,这个句子正是我们想要的结果~
match_phrase 不分词查询结果
1
2
3
4
5
6
7
8
|
GET class_ 1 /_search { "query" : { "match_phrase" : { "name" : "apple so zhen" } } } |
结果:
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
|
{ "took" : 6 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 1 , "relation" : "eq" }, "max_score" : 2.2169428 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "cMfcCoYB090miyjed7YE" , "_score" : 2.2169428 , "_source" : { "name" : "I eat apple so zhen haochi2~" , "num" : 1 } } ] } } |
结果符合预期,只返回了我们想要的那句。那么match
为什么都返回了,这就是前面讲到的分词
,首先会对name: apple so zhen
进行分词,也就是说存在apple
的都会被返回。
当然,真正业务中的需求比这个复杂多了,这里只是为了给大家做区分~ 下面接着看~
多字段全文索引查询
相当于对多个字段执行了match
查询, 这里需要注意的是query
的类型要和字段类型一致,不然会报类型异常
1
2
3
4
5
6
7
8
9
|
GET class_ 1 /_search { "query" : { "multi_match" : { "query" : "apple" , "fields" : [ "name" , "desc" ] } } } |
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
46
47
48
49
|
{ "took" : 5 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 3 , "relation" : "eq" }, "max_score" : 0.752627 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "b8fcCoYB090miyjed7YE" , "_score" : 0.752627 , "_source" : { "name" : "I eat apple so haochi1~" , "num" : 1 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "ccfcCoYB090miyjed7YE" , "_score" : 0.752627 , "_source" : { "name" : "I eat apple so haochi3~" , "num" : 1 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "cMfcCoYB090miyjed7YE" , "_score" : 0.7389809 , "_source" : { "name" : "I eat apple so zhen haochi2~" , "num" : 1 } } ] } } |
范围查询
使用range
来进行范围查询,适用于数组
,时间
等字段
1
2
3
4
5
6
7
8
9
10
11
|
GET class_ 1 /_search { "query" : { "range" : { "num" : { "gt" : 5 , "lt" : 10 } } } } |
返回:
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
46
47
48
49
50
51
52
53
|
{ "took" : 6 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 3 , "relation" : "eq" }, "max_score" : 1.0 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "h2Fg-4UBECmbBdQA6VLg" , "_score" : 1.0 , "_source" : { "name" : "b" , "num" : 6 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "3" , "_score" : 1.0 , "_source" : { "num" : 9 , "name" : "e" , "age" : 9 , "desc" : [ "hhhh" ] } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "1" , "_score" : 1.0 , "_source" : { "name" : "l" , "num" : 6 } } ] } } |
单字段精确查询
使用term
进行非分词字段
的精确查询。需要注意的是,对于那些分词的字段,即使查询的value
是一个完全匹配的短语,也无法完成查询
1
2
3
4
5
6
7
8
9
10
|
GET class_ 1 /_search { "query" : { "term" : { "num" : { "value" : "9" } } } } |
返回:
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
|
{ "took" : 4 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 1 , "relation" : "eq" }, "max_score" : 1.0 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "3" , "_score" : 1.0 , "_source" : { "num" : 9 , "name" : "e" , "age" : 9 , "desc" : [ "hhhh" ] } } ] } } |
字段精确查询 & 多值
与term一样, 区别在于可以匹配一个字段的多个值,满足一个即检索成功
1
2
3
4
5
6
7
8
9
10
11
|
GET class_ 1 /_search { "query" : { "terms" : { "num" : [ 9 , 1 ] } } } |
返回:
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
{ "took" : 8 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 4 , "relation" : "eq" }, "max_score" : 1.0 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "3" , "_score" : 1.0 , "_source" : { "num" : 9 , "name" : "e" , "age" : 9 , "desc" : [ "hhhh" ] } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "b8fcCoYB090miyjed7YE" , "_score" : 1.0 , "_source" : { "name" : "I eat apple so haochi1~" , "num" : 1 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "ccfcCoYB090miyjed7YE" , "_score" : 1.0 , "_source" : { "name" : "I eat apple so haochi3~" , "num" : 1 } }, { "_index" : "class_1" , "_type" : "_doc" , "_id" : "cMfcCoYB090miyjed7YE" , "_score" : 1.0 , "_source" : { "name" : "I eat apple so zhen haochi2~" , "num" : 1 } } ] } } |
文档包含字段查询
为了确定当前索引有哪些文档包含了对应的字段,es
中使用exists
来实现
1
2
3
4
5
6
7
8
|
GET class_ 1 /_search { "query" : { "exists" : { "field" : "desc" } } } |
返回:
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
|
{ "took" : 8 , "timed_out" : false , "_shards" : { "total" : 3 , "successful" : 3 , "skipped" : 0 , "failed" : 0 }, "hits" : { "total" : { "value" : 1 , "relation" : "eq" }, "max_score" : 1.0 , "hits" : [ { "_index" : "class_1" , "_type" : "_doc" , "_id" : "3" , "_score" : 1.0 , "_source" : { "num" : 9 , "name" : "e" , "age" : 9 , "desc" : [ "hhhh" ] } } ] } } |
结束语
本节主要讲了ES
中的文档查询API操作,该部分内容较多, 下节继续给大家讲,就先消化这么多~API
大家都不要去背,多敲几遍就记住了,关键是多用,多总结 。
以上就是ElasticSearch查询文档基本操作实例的详细内容,更多关于ElasticSearch查询文档的资料请关注服务器之家其它相关文章!
原文链接:https://juejin.cn/post/7195023863489511483