3
votes

I have documents with some data and a specific omit list in it (see mapping and example data):

I would like to write an ES query which does the following:

  1. Calculate some "basic" score for the documents (Query 1):

    {
      "explain": true,
      "query": {
        "bool": {
          "should": [
            {
              "constant_score": {
                "filter": {
                  "term": {
                    "type": "TYPE1"
                  }
                }
              }
            },
            {
              "function_score": {
                "linear": {
                  "number": {
                    "origin": 30,
                    "scale": 20
                  }
                }
              }
            }
          ]
        }
      }
    }
    
  2. At the end multiply the score according to the omit percent of a specific id (In the example I used omit valut for A"omit.id": "A"). As a demonstration in Query 2 I calculated this multiplier.

    {
      "query": {
        "nested": {
          "path": "omit",
          "query": {
            "function_score": {
              "query": {
                "filtered": {
                  "query": {
                    "match_all": {}
                  },
                  "filter": {
                    "term": {
                      "omit.id": "A"
                    }
                  }
                }
              },
              "functions": [
                {
                  "linear": {
                    "omit.percent": {
                      "origin": 0,
                      "scale": 50,
                      "offset": 0,
                      "decay": 0.5
                    }
                  }
                }
              ],
              "score_mode": "multiply"
            }
          }
        }
      }
    }
    

To achieve this final multiplication I faced with the following problems:

  • If I calculate linear function score inside of a nested query, (according to my interpretation) I cannot use any other field in function_score query.
  • I cannot multiply the calculated score with any other function_score which is encapsulated into a nested query.

I would like to ask for any advice to resolve this issue.

Note that maybe I should get rid of this nested type and use key-value pairs instead. For example:

{
  "omit": {
    "A": {
      "percent": 10
    },
    "B": {
      "percent": 100
    }
  }
}

but unfortunately there will be a lot of keys, which would result a huge (continuously growing) mapping, so I not prefer this option.

1

1 Answers

2
votes

At least I figured out a possible solution based on a "non-nested way". The complete script can be found here.

I modified the omit list as described in the question:

"omit": {
  "A": {
    "percent": 10
  },
  "B": {
    "percent": 100
  }
}

In addition I set the enabled flag to false to not have these elements in the mapping:

"omit": {
  "type" : "object",
  "enabled" : false
}

The last trick was to use script_score as a function_score's function, because only there I could use the value of percent by _source.omit.A.percent script:

{
  "query": {
    "function_score": {
      "query": {
        ...
      },
      "script_score": {
        "lang": "groovy",
        "script": "if (_source.omit.A){(100-_source.omit.A.percent)/100} else {1}"
      },
      "score_mode": "multiply"
    }
  }
}