Solr Query 和 Filter Query
一. fq vs q
Solr 查询有两个重要的查询操作组成,他们匹配用户查询请求参数以及对匹配的结果集进行排序,以便于匹配度较高的前几个索引文档会被返回。默认的索引文档会基于相关性评分进行排序,这意味着查询结果集被查询并收集到之后,需要一个额外的操作来计算每个匹配的索引文档的相关性评分。
为了高效查询匹配的索引文档以及对匹配的索引文档进行评分,Solr 使用两个参数:fq 和 q。fq 参数代表 Filter Query;q 参数代表 Query。第一眼看到这两个参数感觉很难区分,因为他们拥有相同的查询语法,并且返回相同的查询结果和查询集数量,正因如此,大部分使用者觉得两者的功能是一样的,从而忽略了 fq 的存在。
fq 只有一项单一职责:对匹配的索引文档进行过滤限制,不会对索引文档进行相关性评分操作。
而 q 参数拥有两项职责:
- 根据用户传入的查询条件匹配符合条件的索引文档;
- 使用相关性算法根据 Term 列表对匹配到的索引文档进行相关性评分,这些 Term 列表可能是用户传入的,也可能是对用户输入的查询文本字符串经过分词处理后得到的。
将查询的某些部分分离到 Filter Query 中,那么这些被分离到 Filter Query 的部分匹配到的索引文档将不会进行相关性评分操作,这将大量减少了索引文档相关性评分的计算工作量。
Solr 内部会为每个 Filter Query 分配独立的缓存区来缓存 Filter Query 匹配到的索引文档,那么如果再次使用相同的 Filter Query 时会直接命中缓冲区中的索引文档。鉴于 Filter Query 内部的这种机制,应该将那些能够过滤掉大部分无效文档的查询条件通过 fq 去实现,你也可以将那些用户使用频率较高的查询条件使用 fq 参数实现。
二. fq 和 q 的执行顺序
- 首先每个 fq 参数会在 Fiter 缓存区查找索引文档,如果在缓存中存在,那么会返回命中的 DocSet;
- 如果 q 参数在 Filter 缓存区没有命中且 Filter 缓存开启了,那么会根据 fq 参数构造 Filter Query 从 Solr 索引中加载获取每个索引文档的 DocSet,并存人 Filter 缓存
- 根据 q 参数构造主查询从 Solr 索引中加载匹配的所有索引文档,得到一个索引文档的集合,如果主查询返回的索引文档的内部 ID 在 Filter Query 缓存的 DocSet 中也存在,那么该索引文档就判定为应该返回给用户,然后就对该匹配的索引文档计算相关性评分;
- 如果主查询还包含其他 POST Filter (它会在 Query 和 Filter Query 执行完毕之后才执行),他们还会执行一部分的索引文档收集工作;
三. FilterQuery 的执行顺序
如果你的查询请求中包含了多个 Filter Query,每个 Filter Query 的执行顺序会直接影响你的查询性能,如果一个 Filter Query 提前执行并过滤掉一部分结果集缩小了查询匹配范围,那么接下来执行的 Filter Query 会基于更少的 Document 进行二次查询匹配,其查询速度自然就更快。相反的,如果一个 Filter Query 必须要执行非常复杂的计算,比如 geospatial Filter 需要过滤指定半径的范围内的坐标点,那么此时应该给予更少的索引文档去执行昂贵的 CPU 计算,那么就意味着那些比较昂贵的 FilterQuery 需要尽量靠后执行。
当你清楚地知道 FilterQuery 中哪个执行开销是最昂贵的,Solr 允许你通过指定一个 cost 参数来强制指定 Filter Query 的执行顺序,cost 参数表示对该 Filter Query 执行开销的一个估算数值,数值越大说明该 Filter Query 的执行开销越大,即意味着它应该越靠后执行。cost 参数的具体使用语法如下所示:
fq={!cost=1}category:technology&
fq={!cost=2}date:[NOW/DAY-1YEAR TO *]&
fq={!geofilt pt=37.773,-122.419 sfield=location d=50 cost=3}
当时该 Filter Query 在 Solr 中被称为 Post Filter。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: Lucene 的基本查询语法
下一篇: 谈谈自己对于 AOP 的了解
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论