后过滤器 (post_filter)edit

目前为止,我们可以同时对搜索结果和聚合结果进行过滤(不计算得分的 filter 查询),以及针对聚合结果的一部分进行过滤( filter 桶)。

我们可能会想,"只过滤搜索结果,不过滤聚合结果呢?" 答案是使用 post_filter

它是一个接收过滤器的最高等级的搜索请求元素。这个过滤器在查询 之后 执行(这正是该过滤器的名字的由来:它在查询之后(post) 执行)。正因为它在查询之后执行,它对查询范围没有任何影响,所以对聚合也不会有任何影响。

我们可以利用这个行为对查询条件应用更多的过滤器,而不会影响其他的操作,就如 UI 上的各个分类面。让我们为汽车经销商设计另外一个搜索页面,这个页面允许用户搜索汽车同时可以根据颜色来过滤。颜色的选项是通过聚合获得的:

GET /cars/transactions/_search
{
    "size" : 0,
    "query": {
        "match": {
            "make": "ford"
        }
    },
    "post_filter": {    
        "term" : {
            "color" : "green"
        }
    },
    "aggs" : {
        "all_colors": {
            "terms" : { "field" : "color" }
        }
    }
}

post_filter 元素是一个最高等级(top-level)的元素 (与filter同级别), 而且仅对搜索的命中结果进行过滤。

query 部分找到所有的 ford 汽车,然后用 terms 聚合创建一个颜色列表。因为聚合对查询范围进行操作,颜色列表与福特汽车被喷涂的颜色相对应。

最后, post_filter 会过滤搜索结果,只展示绿色 ford 汽车。这在查询执行过 发生,所以聚合不受影响。

这通常对 UI 的连贯一致性很重要,可以想象用户在界面商选择了一类颜色(比如:绿色),期望的是搜索结果已经被过滤了,而 不是 过滤界面上的选项。如果我们使用 filter 查询,界面会变成 显示 绿色 作为选项,这不是用户想要的!

> 译者注: 这个应该类似于我们的产品列表页面的可用的筛选项目列表. 比如手机的品牌、屏幕大小、内存大小的筛选, 但是貌似这个只能获取一个项目吗??

性能考虑(Performance consideration)

当你需要对搜索结果和聚合结果做不同的过滤时,你才应该使用 post_filter

有时开发人员会在普通搜索中使用 post_filter不要这么做! post_filter 的特性是在查询 之后 执行,任何过滤对性能带来的好处(比如缓存)都会完全失去。

post_filter应该仅被用在 需要不同过滤条件 且 需要聚合时使用。