2

I'm trying to add weight to some results from Elasticsearch.

I'm currently only filtering on an 'active' boolean to grab only the published items:

    query: {
      filtered: {
        query: {
          match: {
            _all: params[:q]
          }
        },
        filter: {
          term: {
            active: true
          }
        }
      },
    }

I now want to add weight to some of my models. For example, a Market should get a +2 boost. I was trying something like this: (search_type is a field on my results, it's basically the Rails model name)

POST _search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "_all": "hospitality"
        }
      },
      "functions": [
          {
            "filter": {
            "term": {
              "active": true
            }
          }
          },
          {
            "filter": {
                "term": {
                    "search_type": "Market"   
                }
            },
            "weight": 2
          }
      ]
    }
  }
}

However, that does not seem to work: "One entry in functions list is missing a function". So I added "weight": 1 to the active filter.. But now it says it can't parse.

I have no experience with ElasticSearch and the docs are quite confusing. I have also tried using a custom_filters_score thing, but that doesn't seem to work for my version of ES (as described here: http://jontai.me/blog/2013/01/advanced-scoring-in-elasticsearch/). Another option I tried was combining a boolean query with must and should, but that returned zero results...

Not sure how to proceed. Some insights would be great.

Joris Ooms
  • 11,880
  • 17
  • 67
  • 124

1 Answers1

2

you should be able to use a filtered query alongside function-score to achieve this

Example:

{
   "query": {
      "filtered": {
         "query": {
            "function_score": {
               "query": {
                  "match": {
                     "_all": "hospitality"
                  }
               },
               "functions": [
                  {
                     "filter": {
                        "term": {
                           "search_type": "Market"
                        }
                     },
                     "weight": 2
                  }
               ]
            }
         },
         "filter": {
            "term": {
               "active": true
            }
         }
      }
   }
}
keety
  • 17,231
  • 4
  • 51
  • 56
  • Hey, thanks. I'll try that. If I want to add more search_type filters, is it just a matter of adding them, or do I need something like an OR filter (not sure if that even exists?) For example, I want to boost Markets and Components with weight 2, News Posts with weight 1.5, something else with 1.2. – Joris Ooms Sep 10 '15 at 20:53
  • you could just add more filters into the function array if the search_type is mutually exclusive they would get the weights associated with the category if not you could use the [score_mode](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#query-dsl-function-score-query) to tweak if the boosts for documents with multiple search_type should be added, multiplied avg,etc – keety Sep 10 '15 at 21:16
  • Hey, I got the query working but the boost doesn't seem to be applied? Am I meant to see the boost in the score field? For example, my top result has: " _score=0.17093952". It's a Market and I gave it a weight of 3. Thanks for helping me out, I'm quite clueless about this. – Joris Ooms Sep 11 '15 at 08:50
  • you could turn on [explain](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-explain.html) to check if weight has been applied. By default the function score is multiplied with the match score. – keety Sep 11 '15 at 14:04