elasticsearch搜索-最基本的工具
搜索-最基本的工具
- 现在我们已经学会了如何使用es作为一个Nosql风格的分布式文件存储系统,
es的真正强大之处在于可以从无规律的数据中找出有意义的信息,从大数据到大信息 - es不只会存储文档,为了能被搜索到也会为文档添加索引,这也是为什么我们使用结构化的json文档
而不是无结构的二进制数据 - 文档中的每个字段都将被索引,并且可以被查询,不仅如此,在简单查询时,es可以使用所有(all)这些索引字段
以惊人的速度返回结果,这是你永远不会考虑用传统数据库去做的一些事情 - 搜索可以做到
- 在类似于gender或者age这样的字段上使用结构化查询,或者join_date这样的字段上使用排序, 就像sql的结构化查询一样
- 全文检索,找出所有匹配关键字的文档并按照相关性(relevance)降序排序后返回结构
- 以上二者兼而有之
- 很多搜索都是开箱即用的,为了充分挖掘es的潜力,需要理解下面三个概念
(1) 映射(mapping),描述数据在每个字段中是如何存储的
(2) 分析(analysis),全文是如何处理可以被搜索到的
(3) 领域特定查询语言(Query DSL),es中强大灵活的查询语言
空搜索
- GET /_search
- 返回结果中最重要的就是hits,它包含total字段来表示匹配到的文档总数,
并且一个hits数组包含所查询结果的前10个文档,
在hits数组中,每个文档包含_index、_id、_score相关性、_source原json文档,
这意味着我们可以直接从返回的搜索结果中使用整个文档,这不像其它搜索引擎,仅仅返回文档的id
需要你单独去获取文档
每个文档都有一个_score,它衡量了文档与查询的匹配程度,默认情况下,首先返回最相关的文档结果,
也就是说,返回的文档,是按照_score降序排序的,在这个例子中,我们没有指定任何查询,
因此所有的文档具有相同的相关性,因此对所有的结果而言1是中性的_score - max_score是与查询文档的_score的最大值
- took值告诉我们执行整个搜索请求耗费了多少毫秒
- _shards告诉我们查询中参与分片的总数,以及这些分片成功了多少个失败了多少个,
加入灾难级故障我们丢失了一个分片和他对应的副本,那么该分片的查询将不能做出响应,
这样的话,es会报告这个分片是失败的,但是还会继续返回剩余分片的结果 - time_out值告诉我们查询是否超时,默认情况下,搜索请求不会超时
如果低响应时间比完成结果更重要,你可以指定timeout为10或者10ms, 或者1s
GET /_search?timeout=1ms
在请求超时之前,es将会返回已经成功从每个分片获取的结果
应当注意的是timeout不是停止查询,
多索引、多类型
- es转发每一个搜索请求到主分片或者副本分片,汇集搜寻出来的前10个结果返回给我们
当我们想在一个索引或者多个索引下搜索文档时,就可以在url中指定对应的索引
GET /gb/_search
GET /gb,us/_search
GET /g*,*s/_search
当在单一的索引下进行搜索的时候,es转发搜索请求到索引的每个分片中,可以是主分片也可以是副本分片
然后从每个分片中收集结果,多索引搜索也是相同的工作方式,只不过是搜索分片会更多一些。
搜索一个索引有5个主分片和搜索5个索引各有一个分片准确来说是等价的
分页
GET /_search?size=5 第一页5条
GET /_search?size=5&from=5 第二页5条
GET /_search?size=5&from=10 第三页5条
考虑到分页深度以及一次请求太多结果的情况,结果集在返回之前先进行排序,但请记住一个请求经常跨越多个分片,
每个分片都产生自己的排序结果,这些结果需要进行集中排序以保证整体顺序是正确的
在分布式系统中深度分页
理解为什么深度分页是有问题的,假设在一个有5个主分片的索引中进行搜索,当我们请求结果的第一页(1-10),
每个分片产生前10的结果,并返回给协调节点,协调节点对50个结果进行排序得到全部结果的前10个
现在假设我们请求第1000也(10001-10010),5个主分片都需要获取前10010个结果,然后发送给协调节点
协调节点需要对50050个结果进行排序获取前10个结果,然后丢掉剩余的50040个
可以看到在分布式系统中,对结果排序的成本随分页的深度成指数上升,
这就是web搜素引擎对任何查询都不要返回超过1000个的原因, 也不要进行深度的分页
轻量搜索
-
有两种形式的搜索API,一种是轻量的查询字符串版本,要求在查询字符串中传递所有参数
另一种是完整的请求体版本,要求使用json格式和更丰富的查询表达式作为搜索语言 -
查询字符串非常适合于命令行做即席查询,
GET/_search?q=tweet:use
下一个查询在 name 字段中包含 john 并且在 tweet 字段中包含 mary 的文档
实际上查询时这样的:+name:john +tweet:mary
, 但是查询字符串参数所需要的 百分比编码 (译者注:URL编码)实际上更加难懂:
GET/_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
-
_all字段
这个简单的搜索返回包含mary的所有文档
GET/_search?q=mary
es是如何在不同的字段中查找到结果的呢,当索引一个文档的时候,es取出所有字段的值拼接成一个大字符串
作为_all字段进行索引,例如当索引这个文档是:
{
"tweet": "However did I manage before Elasticsearch?",
"date": "2014-09-14",
"name": "Mary Jones",
"user_id": 1
}
这就好似增加了一个名叫_all的额外字段,
"However did I manage before Elasticsearch? 2014-09-14 Mary Jones 1"
除非设定特定字段,否则查询字符串就使用_all字段进行搜索
在刚开始开发一个应用时,_all字段是一个很实用的特性,之后你会发现用指定字段来代替_all字段,
将会更好控制搜索结果,当_all字段不在有用的时候,可以将它设置为失效,
- 更复杂的查询
- name 字段中包含 mary 或者 john
- date 值大于 2014-09-10
- _all 字段包含 aggregations 或者 geo
+name:(mary john) +date:>2014-09-10 +(aggregations geo)
查询字符串做了适当的编码后,可读性很差
GET/_search?q=%2Bname%3A(mary+john)+%2Bdate%3A%3E2014-09-10+%2B(aggregations+geo)
所以在生产环境中还是建议使用request body查询API,查了能完成上述所有功能,还有其它功能