Search code examples
elasticsearch

_score for nested documents in Elasticsearch


Is there a way to make _score for nested documents and for thouse parent? For example: Parent _doc title: "car" nested docs: "red", "blue" user searching for red car and the score for parent should be 0.5, and for nested doc "red" 1, for "blue" 0.5 or 0 and if user searching "black car" parent doc should have _score = 0.5 and nested docs may have 0.5 or 0. Is it possible? I need it to give to user a link to a page with a parent doc, or with a nested doc.


Solution

  • You can get the score of the nested documents by using inner_hits and you can disable effect of these scores on the parent scores by wrapping the nested query into constant scorer with boost 0. You can also wrap the parent query into constant_score query in order to remove the effect of IDF and document length normalization. If you combine this all together you will get something like this:

    DELETE test
    PUT test
    {
      "settings": {
        "number_of_shards": 1
      }, 
      "mappings": {
        "properties": {
          "item": {
            "type": "keyword"
          },
          "attributes": {
            "type": "nested",
            "properties": {
              "color": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
    
    PUT test/_bulk?refresh
    {"index": {}}
    {"item": "car", "attributes":[{ "color": "red" }, {"color": "blue"}]}
    {"index": {}}
    {"item": "car", "attributes":[{ "color": "black" }]}
    
    POST test/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "constant_score": {
                "filter": {
                  "simple_query_string": {
                    "query": "red car",
                    "fields": ["item"]
                  }
                }
              }
            },
            {
              "nested": {
                "path": "attributes",
                "inner_hits": {},
                "query": {
                  "constant_score": {
                    "filter": {
                      "simple_query_string": {
                        "query": "red car",
                        "fields": ["attributes.*"]
                      }
                    }
                  }
                },
                "boost": 0
              }
            }
          ]
        }
      }
    }
    

    The elements _score in the response correspond to the scores that you are looking for.