Janusz Guzowski
Janusz Guzowski

Reputation: 43

Elasticsearch - find items in array with score

I need to return a scored list of posts that contain as many tags that user provided as possible. Tags are stored in arrays as objects and user request contains an array of tag IDs (eg. ["a", "c"]). Single document looks something like this:

{
  id: 1,
  meta: {
    tags: [{id: "a", name: "Engine"}, {id: "b", name: "Street"}, {id: "c", name: "Sport"}]
  }
}

Sadly, term query returns posts in almost random order, as all of them have score 1.0:

{
  "query": {
    "bool": {
      "must": [
        {
          "terms": {
            "meta.tags.id.keyword": [
             "a", "c"
            ]
          }
        }
      ]
    }
  }
}

I assume that thing would be quite easy if all tags would be in a single string, as this would be normal full text search, but how to achieve something like this for object arrays?

Here is a mapping exception (dynamically created by NEST client):

"mappings" : {
  "properties" : {
    "categories" : {
      "properties" : {
        "id" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    },
    "description" : {
      "type" : "text",
      "fields" : {
        "keyword" : {
          "type" : "keyword",
          "ignore_above" : 256
        }
      }
    },
    "id" : {
      "type" : "text",
      "fields" : {
        "keyword" : {
          "type" : "keyword",
          "ignore_above" : 256
        }
      }
    },
    "inFavourite" : {
      "type" : "long"
    },
    "likes" : {
      "type" : "long"
    },
    "name" : {
      "type" : "text",
      "fields" : {
        "keyword" : {
          "type" : "keyword",
          "ignore_above" : 256
        }
      }
    },
    "photoPath" : {
      "type" : "text",
      "fields" : {
        "keyword" : {
          "type" : "keyword",
          "ignore_above" : 256
        }
      }
    },
    "meta" : {
      "properties" : {
        "tags" : {
          "properties" : {
            "id" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "name" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
          }
        },
      }
    },
    "userId" : {
      "type" : "text",
      "fields" : {
        "keyword" : {
          "type" : "keyword",
          "ignore_above" : 256
        }
      }
    },
    "viewCounter" : {
      "type" : "long"
    }
  }
}

Upvotes: 1

Views: 337

Answers (1)

KennetsuR
KennetsuR

Reputation: 788

{
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "boost": "5", 
      "functions": [
        {
          "filter": { "match": { "test": "bar" } },
          "random_score": {}, 
          "weight": 23
        },
        {
          "filter": { "match": { "test": "cat" } },
          "weight": 42
        }
      ],
      "max_boost": 42,
      "score_mode": "max",
      "boost_mode": "multiply",
      "min_score": 42
    }
  }
}

Upvotes: 1

Related Questions