Search code examples
elasticsearchsearch-engine

Boosting the tuple in Elasticsearch


I have an apparel data in Elasticsearch document as below. It contains product name, color and material information

/products/data
{
   product_name: "xxxxxx",
   color: "C1",
   material: "M1"
},
{
   product_name: "yyyyyy",
   color: "C2",
   material: "M2"
},
{
   product_name: "zzzzzz",
   color: "C1",
   material: "M2"
}...

Now I want to fetch the 10 products with color: C1 and material: M2. If there are no sufficient products in that combination I want to fetch the products with color: C1 and material: M1. I will be having the combination of color and material. In this example, I have the highest priority to the combination C1, M2, second highest is C1, M1, then it may be C2, M3 and so on. Based on the priority I want to Boost the result (in single query). Is that possible in Elasticsearch?

I'm expecting the returned document to be as below

    {
       _score: highest_score,
       product_name: "xxxxxx",
       color: "C1",
       material: "M2"
    },
    {
       _score: sencond_highest
       product_name: "yyyyyy",
       color: "C1",
       material: "M1"
    },
    {
       _score: third_highest
       product_name: "zzzzzz",
       color: "C2",
       material: "M3"
    }

Sample dataset to reproduce the issue

 POST mat/product
    {
     "pname": "prod1",
     "color": "c1",
     "material": "m1"
    }
    POST mat/product
    {
     "pname": "prod2",
     "color": "c2",
     "material": "m2"
    }
    POST mat/product
    {
     "pname": "prod3",
     "color": "c3",
     "material": "m3"
    }
    POST mat/product
    {
     "pname": "prod4",
     "color": "c1",
     "material": "m2"
    }
    POST mat/product
    {
     "pname": "prod5",
     "color": "c2",
     "material": "m2"
    }
    POST mat/product
    {
     "pname": "prod6",
     "color": "c3",
     "material": "m3"
    }

  GET mat/product/_search
  {
  "query":{
    "bool":{
      "minimum_should_match":1,
      "should":[
        {"bool":{
          "boost":181,
          "must":[{"match":{"color":"c3"}},{"match":{"material":"m3"}}]
        }},
        {"bool":{
          "boost":180,
          "must":[{"match":{"color":"c2"}},{"match":{"material":"m2"}}]
        }},
        {"bool":{
          "boost":179,
          "must":[{"match":{"color":"c1"}},{"match":{"material":"m2"}}]
        }}
]}},"size":10}

Solution

  • Yes, you can use bool/should queries in order to give a different boost to different material/color pairs.

    {
      "query": {
        "bool": {
          "minimum_should_match": 1,
          "should": [
            {
              "bool": {
                "boost": 4,
                "must": [
                  {
                    "match": {
                      "color": {
                        "value": "C1"
                      }
                    }
                  },
                  {
                    "match": {
                      "material": {
                        "value": "M1"
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "boost": 2,
                "must": [
                  {
                    "match": {
                      "color": {
                        "value": "C1"
                      }
                    }
                  },
                  {
                    "match": {
                      "material": {
                        "value": "M2"
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "boost": 1,
                "must": [
                  {
                    "match": {
                      "color": {
                        "value": "C2"
                      }
                    }
                  },
                  {
                    "match": {
                      "material": {
                        "value": "M3"
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }