Elasticsearch query on multiple fields with custom weight

Let's say my index has name and skills.

{
   "name": "Vishnu Prasad",
   "skills": ["devops", "ruby"]
}
{
   "name": "Prasad",
   "skills": ["ruby"]
}
{
   "name": "Jonathan",
   "skills": ["devops"]
}
{
   "name": "Vishnu Prasad A D",
   "skills": ["devops", "nodejs"]
}
{
   "name": "Vishnu",
   "skills": ["devops"]
}
{
   "name": "Vishnu Dinakaran",
   "skills": ["devops"]
}

My criteria are,

field weight
name 10
--------------------- ------------------
skills 9
--------------------- ------------------
field3 8
--------------------- ------------------

When I search for name: Vishnu Prasad and skill: devops, the results should be based on the weight.

If both of the field matches, then it should come first. Also, the score should be more for phrase matches. i.e "Vishnu Prasad" should appear before "Vishnu".

I have written the following query but it is not giving me in the order that I need.

GET test/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "should": [
              {
                "match": {
                  "name": {
                    "query": "Vishnu Prasad",
                  }
                }
              },
              {
                "match": {
                  "skills": {
                    "query": "devops",
                  }
                }
              }
            ]
          }
        }
      ],
      "should": [
        {
          "match_phrase": {
            "name": {
              "query": "Vishnu Prasad",
              "boost": 10
            }
          }
        },
        {
          "match_phrase": {
            "skills": {
              "query": "devops",
              "boost": 9
            }
          }
        }
      ]
    }
  }
}

The order that I need is,

{
   "name": "Vishnu Prasad",
   "skills": ["devops", "ruby"]
}
{
   "name": "Vishnu Prasad A D",
   "skills": ["devops", "nodejs"]
}
{
   "name": "Vishnu Dinakaran",
   "skills": ["devops"]
}
{
   "name": "Vishnu",
   "skills": ["devops"]
}
{
   "name": "Jonathan",
   "skills": ["devops"]
}
{
   "name": "Prasad",
   "skills": ["ruby"]
}

Yes, ranking and scoring is a difficult problem. And to obtain the order that you need, you need to run a lot of experiments with different types and combinations of queries to see what works for you.
Some tools and hints that can work in you case:

For something like this, I would use the query below:

the score should be more for phrase matches. i.e "Vishnu Prasad" should appear before "Vishnu".
I would probably use bool should query:

{
  "query": {
    "bool" : {
      "should" : [
        {"match_phrase" : {"name" : "Vishnu Prasad"}},
        {"match" : {"name" : "Vishnu Prasad"}}
      ]
    }
  }
}

This will ensure if a doc contains a phrase, it will be scored higher.
Then you can one such should query with your name field, another should query with your skills field, and then another higher level should query that will combine these two.

You may also consider experimenting with dis max query and multi match query.

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.