簡體   English   中英

Elasticsearch請求優化(帶有bool查詢的Java API中的奇怪script_score)

[英]Elasticsearch request optimisation (strange script_score in Java API with bool query)

使用Elasticsearch 1.7.0,我想對文檔的文本字段進行查詢。 我需要獲取所有以下文件:

  1. 部分匹配(所有單詞都必須存在同義詞和模糊詞)

  2. 匹配模糊(所有單詞都必須存在+模糊+語音)

  3. 與匹配相關(需要找到單詞的50%)

我用3個Elasticsearch請求制作了一個Java程序,但是這些查詢太長了,因此我嘗試對所有查詢使用一個查詢:

{
  "query": 
    {"bool": {
      "should": [
        {
              "function_score": {
              "boost_mode": "replace",
              "query": {
                "match": {
                  "text.syn": {
                    "query": "sorbone",
                    "operator": "and",
                    "fuzziness": 1,
                    "minimum_should_match": "100%"
                  }
                }
              },
              "script_score": {
                "script": "1"
              }
          }
        },
        {
              "function_score": {
              "boost_mode": "replace",
              "query": {
                "match": {
                  "text.phonetic": {
                    "query": "sorbone",
                    "operator": "and",
                    "fuzziness": 1,
                    "minimum_should_match": "100%"
                  }
                }
              },
              "script_score": {
                "script": "3"
              }
          }
        },
        {
              "function_score": {
              "boost_mode": "replace",
              "query": {
                "match": {
                  "text.phonetic": {
                    "query": "sorbone",
                    "operator": "or",                    
                    "minimum_should_match": "50%"
                  }
                }
              },
              "script_score": {
                "script": "7"
              }
          }
        }
      ]
    }
  }
}

想法是對每個返回的文檔使用帶有特定分數的bool_query。 它運作良好,但是當我嘗試使用Java API進行轉換時,我得到了一個奇怪的分數,而是分數中有小數點,我正等着7 7 1 1 4 10 8這樣的數字對應於分數總和。

我使用的代碼:

            .operator(org.elasticsearch.index.query.MatchQueryBuilder.Operator.AND)
            .fuzziness(Fuzziness.ONE)
            .minimumShouldMatch("100%");
    QueryBuilder termsPhon = matchQuery("text.phonetic", "sorbonne")
            .operator(org.elasticsearch.index.query.MatchQueryBuilder.Operator.AND)
            .fuzziness(Fuzziness.ONE)
            .minimumShouldMatch("100%");
    QueryBuilder termsText = matchQuery("text", "sorbonne")
            .operator(org.elasticsearch.index.query.MatchQueryBuilder.Operator.OR)
            .minimumShouldMatch("50%");
    QueryBuilder functionScorePartial = functionScoreQuery(termsSyn)
            .add(ScoreFunctionBuilders.scriptFunction("1"))
            .boostMode("replace");    


QueryBuilder functionScoreFuzzy = functionScoreQuery(termsPhon)
        .add(ScoreFunctionBuilders.scriptFunction("7"))
        .boostMode("replace");    

QueryBuilder functionScoreRelated = functionScoreQuery(termsText)
        .add(ScoreFunctionBuilders.scriptFunction("15"))
        .boostMode("replace")
        ;    

QueryBuilder boolQ = boolQuery()
        .should(functionScorePartial)
        .should(functionScoreFuzzy)
        .should(functionScoreRelated);

sqb.setQuery(boolQ);


SearchResponse response = sqb.execute().actionGet();
SearchHits hits = response.getHits();

當我查看生成的JSON時,我看到腳本函數的生成方式不同。 在原始的REST中,我有:

"functions" : [ {
      "script_score" : {
        "script" : "1"
      }
    } ],
    "boost_mode" : "replace"

在生成的JSON中,沒有“功能”數組:

 "script_score": {
            "script": "1"
 }

它是Elasticsearch Java API中的錯誤嗎?

match查詢將根據每個匹配查詢的Lucene評分公式(TF-IDF ish)返回一個十進制分數- 然后將其乘以您在查詢中提供的提升。

當查詢包含多個匹配詞(或多個擴展詞匹配)時,這實際上可以為您帶來好處。


對於您要實施的更簡單的評分策略,您需要使用“固定分數查詢”將過濾器包裝在布爾查詢中。 這將允許您為每個匹配條件返回恆定分數


更新 :即使使用恆定分數查詢,由於查詢歸一化,OP也無法從bool查詢中看到預期分數。 使用function_score查詢的最初想法是正確的(用於實現完全自定義評分),但是還通過外部bool查詢進行了查詢規范化。

避免這種規范化的方法是使function_score查詢成為最外面的查詢(並使三個匹配條件成為評分函數):

{
  "query": {
    "function_score": {
      "score_mode": "sum",
      "boost_mode": "replace",
      "filter": {
        "bool": {
          "should": [{
            "query": {
              "match": {
                "text.syn": {
                  "query": "sorbone",
                  "operator": "and",
                  "fuzziness": 1,
                  "minimum_should_match": "100%"
                }
              }
            }
          }, {
            "query": {
              "match": {
                "text.phonetic": {
                  "query": "sorbone",
                  "operator": "or",
                  "minimum_should_match": "50%"
                }
              }
            }
          }]
        }
      },
      "functions": [{
        "filter": {
          "query": {
            "match": {
              "text.syn": {
                "query": "sorbone",
                "operator": "and",
                "fuzziness": 1,
                "minimum_should_match": "100%"
              }
            }
          }
        },
        "weight": 1
      }, {
        "filter": {
          "query": {
            "match": {
              "text.phonetic": {
                "query": "sorbone",
                "operator": "and",
                "fuzziness": 1,
                "minimum_should_match": "100%"
              }
            }
          }
        },
        "weight": 3
      }, {
        "filter": {
          "query": {
            "match": {
              "text.phonetic": {
                "query": "sorbone",
                "operator": "or",
                "minimum_should_match": "50%"
              }
            }
          }
        },
        "weight": 7
      }]
    }
  }
}

請注意,這3個匹配條件中的2個也用作function_score查詢的初始filter子句,因此無需對整個集合進行評分。 (由於過濾的冗余,省略了一個標准,因為100%的語音字詞匹配是50%語音字詞匹配的子集)

將此代碼與constantScoreQuery結合使用,再次給了我分數的浮動數字:(

QueryBuilder boolQ = boolQuery().should(constantScoreQuery(termsSyn).boost(1))
.should(constantScoreQuery(termsPhon).boost(7)).should(constantScoreQuery(termsText).boost(15));
sqb.setQuery(boolQ);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM