为了搜索, For Search, 所以这里深入了解一下ES 中的Search
查询表达式 DSL
使用查询领域特定语言(Query Domain Specific Language)简称DSL, 需要使用JSON作为主体,请求头查询.
query
match
: 模糊匹配, 类似于SQL中的like, 示例:['match' => ['field' => 'keyword']]
match_all
: 简单的匹配所有文档, 示例:['match_all' => new stdClass()]
match_phrase
: 对于短语或者段落镜像精确匹配
match_phrase_prefix
: match_phrase_prefix
与match_phrase
是一样的,只是它允许在文本的最后一项中使用前缀匹配
multi_match
: 匹配多个字段
bool
: 用于表示复合语句,用于组合多个查询语言;将多查询组合成单一查询
must
: 多个查询条件的完全匹配, 相当于and
must_not
: 多个查询条件的相反匹配, 相当于not
should
: 如果满足这些语句中的任意语句,将增加 _score
,否则无任何影响。它们主要用于修正每个文档的相关性得分
minimum_should_match
: 控制需要匹配的 should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比, 如 minimum_should_match: 2
或者 "minimum_should_match": "75%"
filter
: 必须匹配; 但它以不评分、过滤模式来进行.
exists
: 查找包含某个字段的文档
missing
: 查找不包含某个字段的文档
range
: 范围匹配;可以使用大于gt、大于等于gte、小于lt、小于等于lte作为查询条件,可用于数字、日期类型、字符串
term
: 精确查询;对数值,日期,布尔,not_analyzed确切值字符串
terms
: 指定多个匹配值, 如果字段包含其中的任何一个,都会返回文档,类似于SQL中的IN 操作
constant_score
: 恒定分数, 将一个不变的常量评分应用于所有匹配的文档
wildcard
: 通配符, ?
匹配任意字符, *
匹配0或多个字符
fuzzy
: 模糊查询
dis_max
: 分离 最大化查询(Disjunction Max Query)
nested
: 用于操作嵌套类型
highlight
: 高亮, 匹配的结果会被HTML字符包裹住,需要指定匹配的字段
aggs
: 聚合操作, 类似SQL中的Group By
sort
: 排序
from
: 偏移量, 类似于SQL中limit中的offset
size
: 返回数量, 类似于SQL中limit中的count,可以通过from,size来达到分页的效果
DSL查询
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 105 106 107 108 109 110 111 112 113 114 115 116 117
| $params = [ 'index' => 'index_search', 'type' => '_doc', 'body' => [ 'query' => [ 'match' => [ 'username' => 'caoxl', ],
], 'highlight' => [ "pre_tags" => ["<font color='red'>"], "post_tags" => ["</font>"], 'fields' => [ 'username' => new \stdClass() ] ], 'sort' => [ 'id' => ['order' => 'desc'], '_score' => ['order' => 'desc'], ], 'from' => 0, 'size' => 3 ], ]; $res_dsl = $client->search($params); dd($res_dsl);
|
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
| array:4 [ "took" => 1 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 1 "relation" => "eq" ] "max_score" => null "hits" => array:1 [ 0 => array:7 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_1" "_score" => 0.87546873 "_source" => array:9 [ "id" => 1 "username" => "caoxl" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] "highlight" => array:1 [ "username" => array:1 [ 0 => "<font color='red'>caoxl</font>" ] ] "sort" => array:2 [ 0 => 1 1 => 0.87546873 ] ] ] ] ]
|
实例化客户端
1 2 3 4
| $client = ClientBuilder::create() ->setHosts(["localhost:9200"]) ->setRetries(0) ->build();
|
索引文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| $index_doc = [ 'index' => 'index_search', 'type' => '_doc', 'id' => 'search_1', 'body' => [ 'id' => 1, 'username' => 'caoxl', 'nickname' => 'kevin', 'password' => '123456', 'age' => 24, 'sex' => 1, 'tag' => 'Laravel,ElasticSearch', 'signture' => '为了搜索, For Search', 'created_at' => '2019-07-10' ], ];
$response_index_doc = $client->index($index_doc); dd($response_index_doc);
|
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
| array:8 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_4" "_version" => 1 "result" => "created" "_shards" => array:3 [ "total" => 2 "successful" => 1 "failed" => 0 ] "_seq_no" => 3 "_primary_term" => 1 ]
array:8 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_1" "_version" => 2 "result" => "updated" "_shards" => array:3 [ "total" => 2 "successful" => 1 "failed" => 0 ] "_seq_no" => 4 "_primary_term" => 1 ]
|
Match 查询
match 查询: match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。
标准搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $params = [ 'index' => 'index_search', 'type' => '_doc', 'body' => [ 'query' => [ 'match' => [ 'username' => 'caoxl', ], ] ] ];
$res_match = $client->search($params); dd($res_match);
|
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
| array:4 [ "took" => 2 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 1 "relation" => "eq" ] "max_score" => 0.87546873 "hits" => array:1 [ 0 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_1" "_score" => 0.87546873 "_source" => array:9 [ "id" => 1 "username" => "caoxl" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] ] ] ]
|
返回结果说明
took
- 整个搜索请求花费的毫秒数。
timed_out
- 查询超时与否。
一般的,搜索请求不会超时。如果响应速度比完整的结果更重要,你可以定义timeout参数为10或者10ms(10毫秒),或者1s(1秒)
_shards
total
- 参与查询的分片数
successful
- 有多少是成功的
skipped
- 有多少是跳过的
failed
- 有多少的是失败的
hits
total
- 匹配到的文档总数
value
- 匹配到的文档总数
relation
- 一般是eq
相等
max_score
- 所有文档匹配查询中_score
的最大值。
hits
- 命中的文档详情
_index
- 文档索引
_type
- 文档类型
_id
- 文档id
_score
- 相关性得分 (默认按照_score降序排列)
模糊搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $params = [ 'index' => 'index_search', 'type' => '_doc', 'body' => [ 'query' => [ 'wildcard' => [ 'username' => 'caoxl?' ], ] ] ];
$res_match = $client->search($params); dd($res_match);
|
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
| array:4 [ "took" => 1 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 3 "relation" => "eq" ] "max_score" => 1.0 "hits" => array:3 [ 0 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_2" "_score" => 1.0 "_source" => array:9 [ "id" => 2 "username" => "caoxl2" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] 1 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_3" "_score" => 1.0 "_source" => array:9 [ "id" => 3 "username" => "caoxl3" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] 2 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_4" "_score" => 1.0 "_source" => array:9 [ "id" => 4 "username" => "caoxl4" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] ] ] ]
|
Match all 查询
1 2 3 4 5 6 7 8 9 10 11 12
| $params = [ 'index' => 'index_search', 'type' => '_doc', 'body' => [ 'query' => [ 'match_all' => new \stdClass() ] ], ];
$res_all = $client->search($params); dd($res_all);
|
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
| array:4 [ "took" => 1 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 4 "relation" => "eq" ] "max_score" => 1.0 "hits" => array:4 [ 0 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_2" "_score" => 1.0 "_source" => array:9 [ "id" => 2 "username" => "caoxl2" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] 1 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_3" "_score" => 1.0 "_source" => array:9 [ "id" => 3 "username" => "caoxl3" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] 2 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_4" "_score" => 1.0 "_source" => array:9 [ "id" => 4 "username" => "caoxl4" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] 3 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_1" "_score" => 1.0 "_source" => array:9 [ "id" => 1 "username" => "caoxl" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] ] ] ]
|
Bool 查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $params = [ 'index' => 'index_search', 'type' => '_doc', 'body' => [ 'query' => [ 'bool' => [ 'must' => [ ['match' => ['username' => 'caoxl']], ['match' => ['sex' => '1']], ] ] ] ] ];
$res_bool = $client->search($params); dd($res_bool);
|
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
| array:4 [ "took" => 29 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 1 "relation" => "eq" ] "max_score" => 1.8754687 "hits" => array:1 [ 0 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_1" "_score" => 1.8754687 "_source" => array:9 [ "id" => 1 "username" => "caoxl" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-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
| $params = [ 'index' => 'index_search', 'type' => '_doc', 'body' => [ 'query' => [ 'bool' => [ 'must' => [ 'multi_match' => [ 'query' => 'kevin', 'fields' => ['username', 'nickname'] ] ], 'filter' => [ 'term' => ['nickname' => 'kevin'], ], 'should' => [ 'match' => ['nickname' => 'kevin'] ], ], ], 'sort' => [ 'id' => [ 'order' => 'desc' ] ], 'from' => 0, 'size' => 10 ] ];
$res_bool = $client->search($params); dd($res_bool);
|
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
| array:4 [ "took" => 153 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 4 "relation" => "eq" ] "max_score" => null "hits" => array:4 [ 0 => array:6 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_4" "_score" => null "_source" => array:9 [ "id" => 4 "username" => "caoxl4" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] "sort" => array:1 [ 0 => 4 ] ] 1 => array:6 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_3" "_score" => null "_source" => array:9 [ "id" => 3 "username" => "caoxl3" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] "sort" => array:1 [ 0 => 3 ] ] 2 => array:6 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_2" "_score" => null "_source" => array:9 [ "id" => 2 "username" => "caoxl2" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] "sort" => array:1 [ 0 => 2 ] ] 3 => array:6 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_1" "_score" => null "_source" => array:9 [ "id" => 1 "username" => "caoxl" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] "sort" => array:1 [ 0 => 1 ] ] ] ] ]
|
- bool过滤: bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:
- must: 多个查询条件的完全匹配, 相当于and
- must_not: 多个查询条件的相反匹配, 相当于not
- should: 至少有一个查询条件匹配, 相当于or
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
| $params = [ 'index' => 'index_search', 'type' => '_doc', 'body' => [ 'query' => [ 'bool' => [ 'must' => [ 'match' => ['nickname' => 'kevin'], ], 'must_not' => [ 'match' => ['username' => 'caoxl'], ], 'should' => [ 'term' => ['sex' => '1'] ], ], ] ], ];
$res_bool = $client->search($params); dd($res_bool);
|
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
| array:4 [ "took" => 1 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 3 "relation" => "eq" ] "max_score" => 1.0870113 "hits" => array:3 [ 0 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_2" "_score" => 1.0870113 "_source" => array:9 [ "id" => 2 "username" => "caoxl2" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] 1 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_3" "_score" => 1.0870113 "_source" => array:9 [ "id" => 3 "username" => "caoxl3" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] ] 2 => array:5 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_4" "_score" => 1.0870113 "_source" => array:9 [ "id" => 4 "username" => "caoxl4" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-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
| $params = [ 'scroll' => '30s', 'size' => 2, 'index' => 'index_search', 'body' => [ 'query' => [ 'match_all' => new \stdClass() ], 'sort' => [ 'id' => [ 'order' => 'desc' ], ] ] ];
$res_scroll = $client->search($params); dd($res_scroll);
while (isset($res_scroll['hits']['hits']) && count($res_scroll['hits']['hits']) > 0) { $scroll_id = $res_scroll['_scroll_id'];
$res_scroll = $client->scroll([ 'scroll_id' => $scroll_id, 'scroll' => '30s' ]); }
|
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
| array:5 [ "_scroll_id" => "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD8WUnFoQVBUUURUN3lFVWpQVW9FMHhXUQ==" "took" => 0 "timed_out" => false "_shards" => array:4 [ "total" => 1 "successful" => 1 "skipped" => 0 "failed" => 0 ] "hits" => array:3 [ "total" => array:2 [ "value" => 4 "relation" => "eq" ] "max_score" => null "hits" => array:2 [ 0 => array:6 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_4" "_score" => null "_source" => array:9 [ "id" => 4 "username" => "caoxl4" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] "sort" => array:1 [ 0 => 4 ] ] 1 => array:6 [ "_index" => "index_search" "_type" => "_doc" "_id" => "search_3" "_score" => null "_source" => array:9 [ "id" => 3 "username" => "caoxl3" "nickname" => "kevin" "password" => "123456" "age" => 24 "sex" => 1 "tag" => "Laravel,ElasticSearch" "signture" => "为了搜索, For Search" "created_at" => "2019-07-10" ] "sort" => array:1 [ 0 => 3 ] ] ] ] ]
|