1
votes

What I want is to get all documents which match query terms in Title field, and boost the score by value of a field in nested object if the query term also exactly match that nested field.

Following is my example doc:

{
  "Title": "The Heart of the Elastic Stack"
  "QueryClicks": [
      { "Term": "elastic stack", "Count": 100},
      { "Term": "elastic", "Count": 50},
      { "Term": "hard of the elastic", "Count": 200},
  ]
}

And example query DSL:

{
  "query" : {
    "bool" : {
      "must" : [{
          "match" : {
            "Title" : "elastic stack"
          }
        }
      ],
      "should" : [{
          "nested" : {
            "path" : "QueryClicks",
            "query" : {
              "function_score" : {
                "query" : {
                  "match" : {
                    "QueryClicks.Term.lowercaseraw" : "elastic stack"
                  }
                },
                "functions" : [{
                    "script_score" : {
                      "script" : "log(doc['QueryClicks.Count'].value*4)"
                    }
                  }
                ],
                "boost_mode" : "replace"
              }
            }
          }
        }
      ]
    }
  }
}

It somehow works, for certain queryterm, if it match one of the QueryClicks.Term, extra scores will be added to the whole score of the document.

But not perfect, what I want is to multiply the nested function score (that is, log(doc['QueryClicks.Count'].value*4) ) with the parent document's score which calculated in must clause.

If I can get the parent doc's score, then I can do something like this:

"script": "log(doc['QueryClicks.Count'].value*4) * _parent_score"

But since ES does not support getting parent score from nested query yet. Any other approaches?

The purpose is, multiply the _score which calculated by QueryClicks.Count and the _score from must query clause.

2
in order to multiply function score with query score boost_mode should be multiply.user3775217

2 Answers

1
votes

You have used boost_mode as replace. This will neglect your score generated by query. Your current settings for function score will replace score of document with that score of function query only.

To multiply both the score of function query and score generated by query use the following query

{
    "query": {
        "bool": {
            "must": [{
                "match": {
                    "Title": "elastic stack"
                }
            }],
            "should": [{
                "nested": {
                    "path": "QueryClicks",
                    "query": {
                        "function_score": {
                            "query": {
                                "match": {
                                    "QueryClicks.Term.lowercaseraw": "elastic stack"
                                }
                            },
                            "functions": [{
                                "script_score": {
                                    "script": "log(doc['QueryClicks.Count'].value*4)"
                                }
                            }],
                            "boost_mode": "multiply",
                            "score_mode": "sum"
                        }
                    }
                }
            }]
        }
    }
}

Here you can replace score_mode accordingly how you want to evaluate the function score for each score inside the function.

Hope this works for you. Thanks

0
votes

Thanks. I did not answer your questions clearly in previous comments. I try to explain with more details. You are right that score_mode is for combining the scores of all functions inside function array and boost_mode is for combining the score of function with query score.

And what I want is:

  1. Multiply the score of parent doc and the score of nested doc.
  2. The parent doc score is from the {match: {"Title": "elastic stack"}} in must clause.
  3. The nested doc score is calculated by nested doc field QueryClicks.Count, which is wrapped in function_score in nested query in should clause.

So, in my original query DSL, I set boost_mode to "replace", coz the score I want in should clause is actually the score from following script:

"script": "log(doc['QueryClicks.Count'].value*4)"

But since it is in should clause, it will be added to the score from must clause. As I said, I want it is multiplied to score from must clause.

If change "boost_mode" to "multiply" as you suggested, the script score will be multiplied to the score from nested match: "match": {"QueryClicks.Term.lowercaseraw": "elastic stack"}

The associated query ("match": {"QueryClicks.Term.lowercaseraw": "elastic stack"}) of the above script_score is just the precondition of using the script score.

Then this score will be added to the score from must clause. This is not what I want.

Hope this help you understand my requirement.