elasticsearchelasticsearch-dslrelevance

Fetch other document value while framing DSL query


I'm adding a script_score to my DSL query, to boost results based on the price of a source product. something like this:

functions":[
            {
               "script_score":{
                  "script":"if (doc['price'].size() > 0 && doc['price'].value == 1000.0) {15}"
               }
            }
         ],

Here "1000.0" is the price of one document that is not part of the response. To achieve this, I have to query 2 times, first to get the price of that document and then frame the query and add the price to the query and boost the results, which is causing performance degradation.

There should be some way to do this using painless scripting to get the value of an id, but I'm not able to get it. It would be great if someone can help on this. TIA!


Solution

  • Actually, there is a way. I've tried to reproduce your case below, I hope it's close enough to what you have.

    Say, you have one index with prices, i.e. from where you first fetch the document with the price that should be boosted.

    PUT prices/_doc/1
    {
      "price": 1000
    }
    

    Then, your main index is the one that contains the documents on which the second query runs, say it's for products and we have one product with price 1000 and another with price 500.

    PUT products/_doc/q
    {
      "name": "product q",
      "price": 1000
    }
    
    PUT products/_doc/2
    {
      "name": "product 2",
      "price": 500
    }
    

    Now, the query would look like this. In the function_score query we give a boost of 15 (i.e. the hardcoded value in your script) to documents whose price matches the price of the document with ID 1 in the price index. The terms lookup query will fetch the price of 1000 from the specified document (i.e. with ID 1) and then will boost the documents having that price with a weight of 15.

    GET products/_search
    {
      "query": {
        "function_score": {
          "functions": [
            {
              "weight": 15,
              "filter": {
                "terms": {
                  "price": {
                    "index": "prices",
                    "id": "1",
                    "path": "price"
                  }
                }
              }
            }
          ]
        }
      }
    }
    

    I hope this solves your problem.