查询虽然包含这两种,但是查询在不同的执行环境下,操作还是不一样的。
Query与Filter
查询在Query查询上下文和Filter过滤器上下文中,执行的操作是不一样的:
Query查询上下文:
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?之前说过,ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
查询上下文 是在 使用query进行查询时的执行环境,比如使用search的时候。
Filter过滤器上下文:
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用Must_not或者filter。
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
总结
1 查询上下文中,查询操作不仅仅会进行查询,还会计算分值,用于确定相关度;在过滤器上下文中,查询操作仅判断是否满足查询条件
2 过滤器上下文中,查询的结果可以被缓存。
如下例子,查找性别是女,所在的州是PA,过滤条件是年龄是39岁,balance大于等于10000的文档:
{
"query": {
"bool": {
"must": [
{
"match": {
"gender": "F"
}
},
{
"match": {
"state": "PA"
}
}
],
"filter": [
{
"term": {
"age": "39"
}
},
{
"range": {
"balance": {
"gte": "10000"
}
}
}
]
}
}
}
返回结果:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1TPR10dVRUTrR2MkZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jN3QDOwkTN0EDMzETM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
善用filtered query
理解lucence filter工作原理对于写出高性能查询语句至关重要. 许多搜索性能优化都和filter的使用有关. filter使用bitsets进行布尔运算, quey使用倒排索引进行计算, 这是filter比query快的原因 . bitsets的优势主要体现在: 1. bitsetcache在内存里面, 永不消失(除非被LRU). 2. bitsets利用CPU原生支持的位运算操作, 比倒排索引快个数量级 3. 多个bitsets的与运算也是非常的快(一个64位CPU可以同时计算64个DOC的与运算) 4. bitsets 在内存的存储是独立于query的, 有很强的复用性 5. 如果一个bitset片段全是0, 计算会自动跳过这些片段, 让bitsets在数据稀疏情况下同样表现优于倒排索引. 举个例子: query : bool :
tag:'mac' region:'beijing'
title : "apple"
lucence处理这个query的方式是在倒排索引中寻找这三个term的倒排链 ,并使用跳指针技术求交, 在运算过程中需要对每个doc进行算分. 实际上tag和region对于算分并没有作用, 他们充当是过滤器的作用. 这就是过滤器使用场景, 它只存储存在和不存在两种状态. 如果我们把tag和region使用bitsets进行存储, 这样这两个过滤器可以一直都被缓存在内存里面, 这样会快很多. 另外tag和region之间的求交非常迅速, 因为64位机器可以时间一个CPU周期同时处理64个doc的位运算. 一个lucence金科玉律是: 能用filter就用filter, 除非必须使用query(当且仅当你需要算分的时候). 正确的写法为: query : filtered : query: title : "apple" filt er: tag : "elasticsearch" region:"beijing" lucence的filtered query会智能的先计算filter语句, 然后才计算query语句, 尽可能在进行复杂的倒排算法前减少计算空间.