4、ES查询语句
批量索引文档
如果你有大量文档要索引,你能通过批量 API
(bulk API
) 来批量提交它们。批量文档操作比单独提交请求显著更快,因为它极简了网络往返。
最佳的批量数量取决于许多因素:文档的大小和复杂度、索引和搜索的负载以及集群可用资源。一种好的方式是批量处理 1,000 到 5,000 个文档,且总负载在 5 MB 到 15 MB。基于这个,你能尝试找到最佳的方式。
向 Elasticsearch 导入一些数据,你就能开始搜索和分析:
- 下载 accounts.json 示例数据集。这个随机生成的数据集文档表示具体以下信息的用户账户:
{
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}
- 使用以下的
_bulk
请求将账户数据索引到银行(bank
) 索引中:
curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@accounts.json"
curl "localhost:9200/_cat/indices?v=true"
响应表明 1,000 个文档被成功索引:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open bank l7sSYV2cQXmu6_4rJWVIww 5 1 1000 0 128.6kb 128.6kb
查询语句
关于ES的查询语句,我建议还是看一下官方的文档。
一旦你已将一些数据存入 Elasticsearch 索引,你就能通过向 _search
端点发送请求来搜索它。为了获取所有的搜索能力,你可以在请求体中使用 Elasticsearch 的查询 DSL 指定搜索条件。你可以在请求 URI 中指定你想要搜索的索引名称。
例如,以下请求获取按账号排序的银行(bank
)索引中的所有文档:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}
query为查询条件,如果没有是可以省略的,比如这里
默认情况下,响应的命中部分(hits section
)包含符合搜索条件的前10个文档:
{
"took" : 63,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value": 1000,
"relation": "eq"
},
"max_score" : null,
"hits" : [ {
"_index" : "bank",
"_type" : "_doc",
"_id" : "0",
"sort": [0],
"_score" : null,
"_source" : {"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"}
}, {
"_index" : "bank",
"_type" : "_doc",
"_id" : "1",
"sort": [1],
"_score" : null,
"_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
}, ...
]
}
}
这个响应也提供关于搜索请求的以下信息:
took
—— Elasticsearch 执行查询的耗时(毫秒)timed_out
—— 搜索请求是否超时_shards
—— 多少分片被搜索,以及成功、失败或跳过的分片详情max_score
—— 查找到的最相关的文档分数hits.total.value
—— 查找到匹配文档数量hits.sort
—— 文档的排序位置(不按相关分数排序时)hits._score
—— 文档的相关分数(不适用于使用match_all
)
每个搜索请求都是独立的:Elasticsearch 不在请求间维护任何状态信息。在请求中指定 from
和 size
参数用来分页浏览搜索结果。
例如,以下请求获取 10 到 19 的结果:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
],
"from": 10,
"size": 10
}
类比SQL:
select * from bank
order by account_number asc
limit 10
offset 10
现在你已看到如何提交基本查询请求,你可以开始构造比 match_all
更有趣的查询。
为了在字段中搜索指定词语,你可以使用匹配查询。例如,以下的查询搜索地址(address
)字段,用以查找地址包含 mill
或 lane
的客户:
GET /bank/_search
{
"query": { "match": { "address": "mill lane" } }
}
类比SQL(数据库:postgresql):
select *
from bank
where address ~ '(?i)(\s|^)mill(\s|$)'
or address ~ '(?i)(\s|^)lane(\s|$)';
为了执行短语搜索而不是匹配单独的词语,你可以使用 match_phrase
替代 match
。例如,以下请求只匹配包含短语 mill lane
的地址:
GET /bank/_search
{
"query": { "match_phrase": { "address": "mill lane" } }
}
类比SQL:
select * from bank where address like '%mill lane%'
为了构造更复杂的查询,你可以使用包含多个查询条件的 bool
的查询。你可以按必须的(必须匹配)、可选的(应该匹配)或者不必的(必须不匹配)来指定条件。
例如,以下请求搜索银行(bank
)索引中属于 40 岁客户的账号,但排除其中住在爱达荷州(ID
)的人:
GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "state": "ID" } }
]
}
}
}
类比SQL如下:
select * from bank where age = 40 and state != 'ID'
布尔查询中的每个 must
、should
和 must_not
都称为查询子句。文档满足每个 must
或 should
条件子句的程度,有助于文档相关性的分数。分数越高,文档越符合你的搜索条件。默认情况下,Elasticsearch 返回按相关性分数排序的文档。
must_not
子句中的条件被认作过滤器。它影响文档是否包含在结果中,但不影响文档分数。你可以显式地指定任意的过滤器,用来包含或排除基于结构化数据的文档。
例如,以下请求使用范围过滤器用以限定结果中账户余额在 $20,000 和 $30,000(含)之间。
GET /bank/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
查询体(Query Body)
-
query
:这是搜索查询的主体部分。
-
bool
:这是一个布尔查询,允许你组合多个查询条件。
-
must
:这是一个必须满足的条件列表。文档必须满足这个列表中的所有条件才会被返回。
- match_all:这是一个特殊的查询,它会匹配所有文档。在这里,它的作用是确保所有文档都满足“must”条件(实际上,由于它是“match_all”,这个条件总是满足的)。
-
filter
:这是一个过滤条件列表。文档必须满足这个列表中的所有条件,但这些条件不会影响文档的评分。
-
range
:这是一个范围查询,允许你指定一个字段的值应该在某个范围内。
-
balance
:这是我们想要查询的字段名称。
- gte:这是“大于或等于”的缩写,参考
shell
脚本的语法,表示我们想要查询“balance”字段值大于或等于20000的文档。 - lte:这是“小于或等于”的缩写,表示我们想要查询“balance”字段值小于或等于30000的文档。
- gte:这是“大于或等于”的缩写,参考
-
-
-
-
用SQL理解就如下:
SELECT *
FROM bank
WHERE balance >= 20000 AND balance <= 30000;
总结
查询体结构:
GET /bank/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
- query
- bool:表示布尔查询,文档数据必须满足布尔查询内的所有条件
- must/must_not/should:分别表示必须、必须不、也许
- match/match_all/match_phrase:分别表示分词匹配、不基于文本内容的匹配,内部不接受传参且该等式永远成立,即没有要求、不分词匹配
- filter:开启过滤条件,筛选出满足条件的数据
- range
- 字段名
- gte/lte/eq/gt/lt:参考
shell
脚本语法
- gte/lte/eq/gt/lt:参考
- 字段名
- range
- must/must_not/should:分别表示必须、必须不、也许
- bool:表示布尔查询,文档数据必须满足布尔查询内的所有条件
- sort
- 字段名
- from:对应SQL的offset
- size:对应SQL的limit