4

I have a problem with creating a query to Elasticsearch with many conditions. My model looks like:

data class Product(
        @Id
        val id: String? = null,
        val category: String,
        val imagesUrls: List<String>,
        @Field(type = FieldType.Double)
        val price: Double?,
        @Field(type = FieldType.Nested)
        val parameters: List<Parameter>?
)

data class Parameter(
        val key: String,
        val values: List<String>
)

I would like to query products by:

  • category (for example cars)
  • price (between 20k $ and 50k $)
  • and parameters -> For example products with many parameters, like key capacity values 4L, 5L and second parameter gear transmission values manual

My current query looks like this:

GET data/_search
{

  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "category.keyword": {
              "value": "cars"
            }
          }
        },
        {
          "nested": {
            "path": "parameters",
            "query": {
              "bool": {
                "must": [
                  {"term": {
                    "parameters.key.keyword": {
                      "value": "Capacity"
                    }
                  }},
                  {
                    "term": {
                      "parameters.key": {
                        "value": "4L, 5L"
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
  • Could you tell me how to filter the product when parameter key is equal to Capacity and check that the values list contains one of the values?
  • How to combine many this kind operations in one query?

Example data:

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"capacity",
         "values":"4L"
      },
      {
         "key":"gear transmission",
         "values":"automcatic"
      }
   ]
}
6
  • Can you share a sample JSON doc? Commented Sep 13, 2020 at 21:02
  • Yes, of course. Just added. Commented Sep 13, 2020 at 21:11
  • @Ice did you get a chance to go through my answer, looking forward to get feedback from you :) Commented Sep 16, 2020 at 18:05
  • @BhavyaGupta I saw your answer, I will check it tomorrow and of course, I will add feedback :) Commented Sep 16, 2020 at 22:48
  • @Ice your bounty is going to expire in just 11 hours, it would be great if you can go through my answer, and please don't forget to upvote and accept my answer if it helped you resolve your query :) Commented Sep 22, 2020 at 9:08

2 Answers 2

1
+50

The search query shown below queries the data based on:

  1. category (for example cars)
  2. And parameters -> For example products with many parameters, like key capacity values 4L, 5L and second parameter gear transmission values manual

Adding a working example with index data, mapping, search query, and search result

Index Mapping:

{
  "mappings": {
    "properties": {
      "parameters": {
        "type": "nested"
      }
    }
  }
}

Index Data:

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"gear transmission",
         "values":["4L","5L"]
      },
      {
         "key":"capacity",
         "values":"automcatic"
      }
   ]
}

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"capacity",
         "values":["4L","5L"]
      },
      {
         "key":"gear transmission",
         "values":"automcatic"
      }
   ]
}

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"capacity",
         "values":"4L"
      },
      {
         "key":"gear transmission",
         "values":"automcatic"
      }
   ]
}

Search Query:

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "category.keyword": {
              "value": "cars"
            }
          }
        },
        {
          "nested": {
            "path": "parameters",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "parameters.key": "capacity"
                    }
                  },
                  {
                    "terms": {
                      "parameters.values": [
                        "4l",
                        "5l"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "parameters",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "parameters.key": "gear transmission"
                    }
                  },
                  {
                    "match": {
                      "parameters.values": "automcatic"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

Search Result:

"hits": [
         {
            "_index": "bstof",
            "_type": "_doc",
            "_id": "1",
            "_score": 3.9281754,
            "_source": {
               "category": "cars",
               "name": "Ferrari",
               "price": 50000,
               "parameters": [
                  {
                     "key": "capacity",
                     "values": "4L"
                  },
                  {
                     "key": "gear transmission",
                     "values": "automcatic"
                  }
               ]
            }
         },
         {
            "_index": "bstof",
            "_type": "_doc",
            "_id": "2",
            "_score": 3.9281754,
            "_source": {
               "category": "cars",
               "name": "Ferrari",
               "price": 50000,
               "parameters": [
                  {
                     "key": "capacity",
                     "values": [
                        "4L",
                        "5L"
                     ]
                  },
                  {
                     "key": "gear transmission",
                     "values": "automcatic"
                  }
               ]
            }
         }
      ]
Sign up to request clarification or add additional context in comments.

Comments

0

When you need to match any one from a list then you can use terms query instead of term. Update the part in query from:

{
  "term": {
    "parameters.key": {
      "value": "4L, 5L"
    }
  }
}

to below:

{
  "terms": {
    "parameters.values": {
      "value": [
        "4L",
        "5L"
      ]
    }
  }
}

Note that if parameters.key is analysed field and there exist a keyword sub-field for the same, then use it instead. e.g parameters.values.keyword

You can read more on terms query here.

4 Comments

But how you make sure that you are checking parameter values under proper key? How this query will looks like for two car with capacity -> 4L and gear transmission" -> manual?
Sorry, one car with two parameters to query by.
Well that is the application business logic.
It can't be. It has to be a way to do this on the elasticsearch

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.