查询结果的过滤
3.5 查询结果的过滤
本书已经介绍了如何使用不同的条件和查询来构建查询并搜索数据。我们还熟知了评分(参
见1.1.3节),它告诉我们在给定的查询中,哪些文档更重要以及查询文本如何影响排序。然而,
有时我们可能要在不影响最后分数的情况下,选择索引中的某个子集,这就要使用过滤器(当然
不是唯一的原因)。
老实说,应该尽可能使用过滤器。过滤器不影响评分,而得分计算让搜索变得复杂,而且需
要CPU资源。另一方面,过滤是一种相对简单的操作。由于过滤应用在整个索引的内容上,过滤
的结果独立于找到的文档,也独立于文档之间的关系。过滤器很容易被缓存,从而进一步提高过
滤查询的整体性能。
{ "query": { "filtered" : { "query" : { "match" : { "title" : "Catch-22" } }, "filter" : { "term" : { "year" : 1961 } } } } }
3.5.2
过滤器类型
1. 范围过滤器
范围过滤器可以用来限制只搜索那些字段值在给定边界之间的文档。例如,为了创建一个过 滤器来过滤只在1930~1990年之间出版的图书,在查询中加入以下部分:
{ "post_filter" : { "range" : { "year" : { "gte": 1930, "lte": 1990 } } } }
2.missing过滤器
3.exists过滤器
exists过滤器非常简单。它过滤掉给定字段上没有值的文档。比如,考虑下面的代码:
{ "post_filter" : { "exists" : { "field": "year" } } }
上述过滤器将只返回year字段有值的文档。
missing过滤器跟exists过滤器相反,它过滤掉给定字段上有值的文档。然而,它还有一 些额外的功能。除了选择指定字段缺失的文档,可以指定Elasticsearch对空字段的定义。这有助 于在输入数据中包含null、EMPTY、not-defined等词条的情况。我们修改先前的例子,找没 有定义year字段、或者year字段为0的那些文档。修改过的过滤器将如下所示:
{ "post_filter" : { "missing" : { "field": "year", "null_value": 0, "existence": true } } }
在前面的示例中,有两个额外参数。existence参数告诉Elasticsearch应该检查指定字段上 存在值的文档,null_value参数定义了应该被视为空的额外值。如果你没有定义null_value, existence将被设为默认值;所以,在这个例子中可以省略existence。
4.脚本过滤器
有时,我们想要通过计算值来过滤文档。一个例子是:可以过滤掉所有发表在一个世纪以前 的书。使用脚本过滤器来实现,如下所示:
{ "post_filter" : { "script" : { "script" : "now - doc['year'].value > 100", "params" : { "now" : 2012 } } } } }
可以看到,我们使用了一个简单的脚本来计算值,并从中过滤数据。
5.类型过滤器
想限制返回文档的类型为book,使用下列过滤器:
{ "post_filter" : { "type": { "value" : "book" } } }
类型过滤器专门用来限制文档的类型。当查询运行在多个索引上,或单个索引但有很多类型 时,可以使用这个过滤器。
6.限定过滤器
{ "post_filter" : { "limit" : { "value" : 1 } } }
当我们对分片数量使用默认设置时,上述过滤器返回5个文档。因为在Elasticsearch中,索引 默认分为5个分片。查询分别运行在各个分片上,而每个分片最多返回1个文档。
限定过滤器限定单个分片返回的文档数目。
7.标识符过滤器
要排除标识符等于1的文档, 可使用类似下面的代码:
{ "post_filter": { "ids" : { "type": ["book"], "values": [1] } } }
需要过滤成若干具体的文档时,可以使用标识符过滤器。
8.
Elasticsearch支持下列专用过滤器:
bool过滤器;
geo_shape过滤器;
has_child过滤器;
has_parent过滤器;
ids过滤器;
indices过滤器;
match_all过滤器;
nested过滤器;
prefix过滤器;
range过滤器;
regexp过滤器;
term过滤器;
terms过滤器。
9.
组合过滤器
{
"post_filter": {
"not": {
"and": [
{
"term": {
"title": "Catch-22"
}
},
{
"or": [
{
"range": {
"year": {
"gte": 1930,
"lte": 1990
}
}
},
{
"term": {
"available": true
}
}
]
}
]
}
}
}
10.
命名过滤器
记住在大多数情况下,filtered查询比post_filter更快。所以在可能的 情况下,尽可能使用filtered查询。