• 最佳字段查询的调优
    • tie_breaker

    最佳字段查询的调优

    如果用户(((“multifield search”, “best fields queries”, “tuning”)))(((“best fields queries”, “tuning”)))搜索的是”quick pets”,那么会发生什么呢?两份文档都包含了单词quick,但是只有文档2包含了单词pets。两份文档都没能在一个字段中同时包含搜索的两个单词。

    一个像下面那样的简单dis_max查询会选择出拥有最佳匹配字段的查询子句,而忽略其他的查询子句:

    1. {
    2. "query": {
    3. "dis_max": {
    4. "queries": [
    5. { "match": { "title": "Quick pets" }},
    6. { "match": { "body": "Quick pets" }}
    7. ]
    8. }
    9. }
    10. }

    // SENSE: 110_Multi_Field_Search/15_Best_fields.json

    1. {
    2. "hits": [
    3. {
    4. "_id": "1",
    5. "_score": 0.12713557, <1>
    6. "_source": {
    7. "title": "Quick brown rabbits",
    8. "body": "Brown rabbits are commonly seen."
    9. }
    10. },
    11. {
    12. "_id": "2",
    13. "_score": 0.12713557, <1>
    14. "_source": {
    15. "title": "Keeping pets healthy",
    16. "body": "My quick brown fox eats rabbits on a regular basis."
    17. }
    18. }
    19. ]
    20. }

    <1> 可以发现,两份文档的分值是一模一样的。

    我们期望的是同时匹配了title字段和body字段的文档能够拥有更高的排名,但是结果并非如此。需要记住:dis_max查询只是简单的使用最佳匹配查询子句得到的_score。

    tie_breaker

    但是,将其它匹配的查询子句考虑进来也是可能的。通过指定tie_breaker参数:

    1. {
    2. "query": {
    3. "dis_max": {
    4. "queries": [
    5. { "match": { "title": "Quick pets" }},
    6. { "match": { "body": "Quick pets" }}
    7. ],
    8. "tie_breaker": 0.3
    9. }
    10. }
    11. }

    // SENSE: 110_Multi_Field_Search/15_Best_fields.json

    它会返回以下结果:

    1. {
    2. "hits": [
    3. {
    4. "_id": "2",
    5. "_score": 0.14757764, <1>
    6. "_source": {
    7. "title": "Keeping pets healthy",
    8. "body": "My quick brown fox eats rabbits on a regular basis."
    9. }
    10. },
    11. {
    12. "_id": "1",
    13. "_score": 0.124275915, <1>
    14. "_source": {
    15. "title": "Quick brown rabbits",
    16. "body": "Brown rabbits are commonly seen."
    17. }
    18. }
    19. ]
    20. }

    <1> 现在文档2的分值比文档1稍高一些。

    tie_breaker参数会让dis_max查询的行为更像是dis_max和bool的一种折中。它会通过下面的方式改变分值计算过程:

    • 1.取得最佳匹配查询子句的_score。
    • 2.将其它每个匹配的子句的分值乘以tie_breaker。
    • 3.将以上得到的分值进行累加并规范化。

    通过tie_breaker参数,所有匹配的子句都会起作用,只不过最佳匹配子句的作用更大。

    提示:tie_breaker的取值范围是0到1之间的浮点数,取0时即为仅使用最佳匹配子句(译注:和不使用tie_breaker参数的dis_max查询效果相同),取1则会将所有匹配的子句一视同仁。它的确切值需要根据你的数据和查询进行调整,但是一个合理的值会靠近0,(比如,0.1 -0.4),来确保不会压倒dis_max查询具有的最佳匹配性质。