搜索你的数据
前面我们讲了如何通过RESTful API创建索引,那么如何搜索已经存在的索引数据呢?
搜索API
Elasticsearch提供了两种基本的方式进行搜索:一种是通过REST请求URI传递搜索参数,另一种是通过REST请求体传递参数。搜索的REST API是”_search”,下面的命令是要搜索bank中的所有数据:
curl ‘localhost:9200/userindex/_search?q=*&pretty’
响应的结果(部分)如下:
{
"took": 663,
"timed_out": false,
"_shards": {
"total": 16,
"successful": 16,
"failed": 0
},
"hits": {
"total": 307843698,
"max_score": 1,
"hits": [
{
"_index": "userindex",
"_type": "951",
"_id": "95131620",
"_score": 1,
"_source": {
"uid": 95131620,
"cell": "1725895131620",
"appId": "951",
"phoneType": "ANDROID",
"province": "北京",
"tags": "1 2 3 4 5”,
"city": "11000000",
"sex": 70,
"price": 1000,
"usertype": "10001",
"mobiler": "1",
"userTag": ""
}
}
]
}
}
其中,部分字段的含义如下:
took:花费的时间
time_out:显示是否超时
_shards:搜索了多少分片,成功/失败搜索的分片数量
hits:搜索命中的结果
hits.total:命中的数量
_score和max_score:匹配得分
第二种搜索方式,使用请求体:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
“query”: {“match_all”: {} }
}’
查询简介
对上面的查询语句,”query”部分表示要进行查询操作,而”match_all”表示得到索引中的全部文档。除了”query”参数,还可以增加其他参数,比如还是要搜索全部文档,不过只返回第一个文档:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
“query”: { “match_all”: {} },
“size”: 1
}’
如果”size”未特别说明,默认返回10条结果。下面的例子返回文档11到20:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
“query”: { “match_all”: {} },
“from”: 10,
“size”: 1
}’
当对搜索结果分页时,这个功能非常有用。下面的例子返回10条结果(默认size)并根据balance降序排序:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ’
{
“query”: {“match_all”: {} },
“sort”: {“balance”: {“orde”: “desc”}}
}’
查询操作
之前的查询都将源数据全部返回,现在介绍只让我们想要的字段返回,比如下面的例子只返回两个字段”account_number”和”balance”:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
“query”: {“match_all”: {} } ,
“_source”: [“account_number”, “balance”]
}’
然后再看”query”字段的匹配,比如下面的例子返回编号是20的账户:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
“query”: {“match”:{ “account_number”:20 } }
}’
然后返回地址中包含”mill”的账户:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
“query”: {“match”: {“address”: “mill”}}
}’
下面的例子返回的结果是地址中包含”mill”或”lane”的账户:
$curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
“query”: {“match”: {“address”: ”mill lane”}}
}’
区别上面的例子,使用”match_phrase”关键词,下面的例子返回包含词组”mill lane”的账户:
curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d
{
“query” : {“match_phrase”: {“address”:”mill lane”}}
}’
下面在介绍一些布尔查询的例子,首先介绍与查询:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
返回地址中既包含”mill”又包含”lane”的账户。然后或查询,地址中包含”mill”或”lane”:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
既不包含”mill”又不包含”lane”:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must_not": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
在布尔查询中,可以随意组合布尔子句,例如下面的子句查询年龄40岁,但不在ID州的账户:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "state": "ID" } }
]
}
}
}'
使用过滤器
前面介绍过查询结果中会回馈一个字段”_score”,这是查询和文档相关度的一个度量,值越大表示相关度越大,而值越小表示相关度越小。但有时,Elasticsearch提供了另一查询功能——过滤器。过滤器和查询的概念相似,但却比查询要快,基于下面两个原因:
(1) 过滤器不需要评分
(2) 过滤器通过缓存使得重复检索速度非常快
过滤器可以和查询一起使用,例如下面的例子查询余额在20000到30000之间(包含)的账号:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"filtered": {
"query": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}'
这个命令包含了一个”match_all”查询和一个范围过滤器
使用聚合
聚合提供了分组和统计的能力,关于聚合的理解,可以类比SQL中的GROUP BY或SQL聚合函数。下面的例子将所有的账户按照州聚合,并且按照默认值返回排名前10的州,并按照默认的降序排列:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state"
}
}
}
}'
上面的命令类似于SQL中的:
SELECT COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC