本书基于 Elasticsearch 2.x 版本,有些内容可能已经过时。 Elasticsearch: 权威指南 » 深入搜索 » 部分匹配 » prefix 前缀查询 « 邮编与结构化数据 通配符与正则表达式查询 »
prefix 前缀查询编辑
为了找到所有以 W1
开始的邮编,可以使用简单的 prefix
查询:
GET /my_index/address/_search { "query": { "prefix": { "postcode": "W1" } } }
prefix
查询是一个词级别的底层的查询,它不会在搜索之前分析查询字符串,它假定传入前缀就正是要查找的前缀。
默认状态下, prefix
查询不做相关度评分计算,它只是将所有匹配的文档返回,并为每条结果赋予评分值 1
。它的行为更像是过滤器而不是查询。 prefix
查询和 prefix
过滤器这两者实际的区别就是过滤器是可以被缓存的,而查询不行。
之前已经提过:“只能在倒排索引中找到存在的词”,但我们并没有对这些邮编的索引进行特殊处理,每个邮编还是以它们精确值的方式存在于每个文档的索引中,那么 prefix
查询是如何工作的呢?
回想倒排索引包含了一个有序的唯一词列表(本例是邮编)。 对于每个词,倒排索引都会将包含词的文档 ID 列入 倒排表(postings list) 。与示例对应的倒排索引是:
Term: Doc IDs: ------------------------- "SW5 0BE" | 5 "W1F 7HW" | 3 "W1V 3DG" | 1 "W2F 8HW" | 2 "WC1N 1LZ" | 4 -------------------------
为了支持前缀匹配,查询会做以下事情:
-
扫描词列表并查找到第一个以
W1
开始的词。 - 搜集关联的文档 ID 。
- 移动到下一个词。
-
如果这个词也是以
W1
开头,查询跳回到第二步再重复执行,直到下一个词不以W1
为止。
这对于小的例子当然可以正常工作,但是如果倒排索引中有数以百万的邮编都是以 W1
开头时,前缀查询则需要访问每个词然后计算结果!
前缀越短所需访问的词越多。如果我们要以 W
作为前缀而不是 W1
,那么就可能需要做千万次的匹配。
prefix
查询或过滤对于一些特定的匹配是有效的,但使用方式还是应当注意。
当字段中词的集合很小时,可以放心使用,但是它的伸缩性并不好,会对我们的集群带来很多压力。可以使用较长的前缀来限制这种影响,减少需要访问的量。
本章后面会介绍另一个索引时的解决方案,这个方案能使前缀匹配更高效,不过在此之前,需要先看看两个相关的查询: wildcard
和 regexp
(模糊和正则)。
Getting Started Videos
- Starting Elasticsearch
- Introduction to Kibana
- Logstash Starter Guide
官方地址:https://www.elastic.co/guide/cn/elasticsearch/guide/current/prefix-query.html