ES中搜索的方式分为两种
,一种是通过URL参数
进行搜索;另一种是通过POST
中body请求参数
进行搜索。
针对第一种我们进行简单的讲解,我们关注的核心放在第二种上面。
一、简单搜索(search)
1.1 测试使用的index、mapping及数据准备
PUT example
PUT example/docs/_mapping
{
"properties": {
"id": {
"type": "long"
},
"orderNo": {
"type": "keyword"
},
"buyerId": {
"type": "long"
},
"shopId": {
"type": "long"
},
"shopName": {
"type": "text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"tradeStatus": {
"type": "integer"
},
"payStatus": {
"type": "integer"
},
"orderAmount": {
"type": "float"
},
"payAmount": {
"type": "float"
},
"payPlatformOrderNo": {
"type": "keyword"
},
"delivery": {
"properties": {
"receiver": {
"type": "keyword"
},
"phoneNumber": {
"type": "keyword"
},
"address": {
"type": "keyword"
},
"detailedAddress": {
"type": "keyword"
}
}
},
"items": {
"type": "nested",
"properties": {
"id": {
"type": "long"
},
"orderId": {
"type": "long"
},
"goodId": {
"type": "long"
},
"goodName": {
"type": "keyword"
},
"goodPrice": {
"type": "float"
},
"goodNumber": {
"type": "integer"
},
"goodAmount": {
"type": "float"
},
"createTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss",
"ignore_malformed": true
}
}
},
"createTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss",
"ignore_malformed": true
},
"deliveryTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss",
"ignore_malformed": false
},
"deliveryAmount": {
"type": "float"
},
"remark": {
"type": "text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
}
}
}
#bulk插入
POST example/docs/_bulk
{"index": {"_id": 1}}
{"id":1,"orderNo":1136482742505680898,"buyerId":4500,"shopId":9596,"shopName":"小米手机官方旗舰店","tradeStatus":1,"payStatus":1,"orderAmount":4290.90,"payAmount":4280.00,"payPlatformOrderNo":"9b235e16-ffa2-4605-af8c-47bee94d1732","delivery":{"receiver":"张三","phoneNumber":"13279220508","address":"陕西省西安市雁塔区","detailedAddress":"小寨东路91号陕西历史博物馆"},"items":[{"id":123,"orderId":1,"goodId":54,"goodName":"小米CC9Pro","goodPrice":3299.00,"goodNumber":5468,"goodAmount":1,"createTime":"2019-11-11 00:01:18"},{"id":124,"orderId":1,"goodId":55,"goodName":"小米插线板","goodPrice":49.00,"goodNumber":5469,"goodAmount":2,"createTime":"2019-11-11 00:01:18"},{"id":125,"orderId":1,"goodId":56,"goodName":"小米平衡车","goodPrice":1999.00,"goodNumber":5470,"goodAmount":1,"createTime":"2019-11-11 00:01:18"}],"createTime":"2019-11-11 00:01:18","deliveryTime":"2019-11-11 16:30:22","deliveryAmount":20.00,"remark":"尽快发货,谢谢!"}
{"index": {"_id": 2}}
{"id":2,"orderNo":1136482742505656781,"buyerId":4500,"shopId":9500,"shopName":"华为旗舰店","tradeStatus":1,"payStatus":1,"orderAmount":7999.99,"payAmount":6500.00,"payPlatformOrderNo":"9b235e16-ffa2-4605-af8c-47bee94d2134","delivery":{"receiver":"张三","phoneNumber":"13279220508","address":"陕西省西安市雁塔区","detailedAddress":"小寨东路91号陕西历史博物馆"},"items":[{"id":124,"orderId":2,"goodId":1003,"goodName":"华为笔记本","goodPrice":7999.99,"goodNumber":5400,"goodAmount":1,"createTime":"2019-11-11 00:01:18"}],"createTime":"2019-11-11 00:01:18","deliveryTime":"2019-11-12 18:30:22","deliveryAmount":0.00,"remark":"尽快发货,谢谢!"}
{"index": {"_id": 3}}
{"id":3,"orderNo":1136482742505655433,"buyerId":4501,"shopId":8503,"shopName":"无印良品旗舰店","tradeStatus":1,"payStatus":1,"orderAmount":2036.00,"payAmount":2020.00,"payPlatformOrderNo":"9b235e16-ffa2-4605-af8c-47bee94d2300","delivery":{"receiver":"李四","phoneNumber":"13279228888","address":"陕西省西安市长安区","detailedAddress":"西长安街1号大厦"},"items":[{"id":620,"orderId":3,"goodId":8784,"goodName":"柔和洗面奶","goodPrice":79.90,"goodNumber":8780,"goodAmount":1,"createTime":"2019-11-11 00:21:50"},{"id":622,"orderId":3,"goodId":8704,"goodName":"化妆水","goodPrice":109.90,"goodNumber":8580,"goodAmount":2,"createTime":"2019-11-11 00:21:50"}],"createTime":"2019-11-11 00:21:50","deliveryTime":"2019-11-13 17:35:23","deliveryAmount":8.00,"remark":"尽快发货,谢谢!"}
1.2 示例
在这里我们只做简单的示例,不做过多的学习,有过Http基础的话,基本没有什么难度。
#查询所有
GET example/docs/_search
#带有参数的查询
GET example/docs/_search?
#在索引example和us的所有类型中搜索
GET example,us/_search
# 在以g或u开头的索引的所有类型中搜索
GET e*,u*/_search
#在索引example和us的类型为docs和docs2中搜索
GET example,us/docs,docs2/_search
注意:当你搜索包含单一索引时,Elasticsearch转发搜索请求到这个索引的主分片或每个分片的复制分片上,然后聚集每个分片的结果。搜索包含多个索引也是同样的方式——只不过或有更多的分片被关联。
可以跟的参数如下图所示。其实这些方式归根到底第二种方式的功能是重合的。
二、 结构化搜索(request body search)
请求体的参数是JSON
格式。这种JSON必须遵循DSL(domain search language)
语法格式。在这里我们简单做一下示例使用。关于更多的查询和使用会在后续的文章逐一详细介绍。
2.1 查询所有
GET example/docs/_search
{
"query": {
"match_all": {}
}
}
2.2 分页搜索
和SQL
使用LIMIT
关键字返回只有一页的结果一样,Elasticsearch
接受from
和size
参数:
size
: 结果数,默认10
from
: 跳过开始的结果数,默认0
。可理解成元素开始的索引下标
。
例如我们想分页搜索订单的第一页,每页显示2个。
GET example/docs/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 2
}
应该当心分页太深或者一次请求太多的结果。结果在返回前会被排序。但是记住一个搜索请求常常涉及多个分片。每个分片生成自己排好序的结果,它们接着需要集中起来排序以确保整体排序正确。
小贴士
在集群系统中深度分页。为了理解为什么深度分页是有问题的,让我们假设在一个有5个主分片的索引中搜索。当我们请求结果的第一页(结果1到10)时,每个分片产生自己最顶端10个结果然后返回它们给请求节点(requesting node),它再排序这所有的50个结果以选出顶端的10个结果。
现在假设我们请求第1000页——结果10001到10010。工作方式都相同,不同的是每个分片都必须产生顶端的10010个结果。然后请求节点排序这50050个结果并丢弃50040个!你可以看到在分布式系统中,排序结果的花费随着分页的深入而成倍增长。这也是为什么网络搜索引擎中任何语句不能返回多于10000个结果的原因(通常最大的分页数就是100页,比如说京东的评论数等等)。