Let's assume that I have the following documents stored in Elasticsearch:
{
id: '349dec5f-4ddf-4faa-beb0-79a0ea08bad6',
name: 'Iphone 13',
criteria: [
{
name: 'color',
options: ['Midnight', 'Blue', 'Green'],
},
]
},
{
id: '1a63de5a-4335-4e0d-83ab-c820d57709bd',
name: 'IPhone 14',
criteria: [
{
name: 'color',
options: ['Midnight', 'Purple', 'Red'],
},
{
name: 'size',
options: ['128GB', '256GB'],
},
]
},
{
id: 'eae5672f-2153-4f7d-be68-122e6d9fe5e1',
name: 'Iphone 14 Pro',
criteria: [
{
name: 'color',
options: ['Black', 'Blue', 'Red'],
},
{
name: 'size',
options: ['64GB', '128GB', '256GB'],
},
]
}
And I have the following type mappings for these documents:
"properties": {
"id": { "type": "keyword", "ignore_above": 36 },
"name": { "type": "text" },
"category": { "type": "keyword", "ignore_above": 36 },
"criteria": {
"type": "nested",
"properties": {
"name": { "type": "keyword", "ignore_above": 500 },
"options": { "type": "keyword", "ignore_above": 500 }
}
}
}
Note that criteria
is a nested array of objects with two fields criteria.name
and criteria.options
, so it can have not only color
and size
, but other values as well.
And I want to filter these documents by particular color
and size
, for example, when I get the following filter
object in an HTTP request:
{
search: null,
filter: {
criteria: [
{
name: 'color',
options: ['Blue', 'Red'],
operator: 'OR'
},
{
name: 'size',
options: ['64GB', '128GB'],
operator: 'OR'
}
]
}
}
I need to get documents that have 'Blue'
or 'Red'
color AND '64GB'
OR '128GB'
size, so, it looks something like this:
if criteria.name == 'color' THEN
criteria.options should include one of ['Blue', 'Red']
if criteria.name == 'size' THEN
criteria.options should include one of ['64GB', '128GB']
So, for example, for the above filter
object in the response, I should return two documents, the first with name: 'IPhone 14'
and the second with name: 'Iphone 14 Pro'
because the first one (name: 'IPhone 14'
) has a "Red" color and a size of "128GB", and the second (name: 'Iphone 14 Pro'
) has both "Blue" and "Red" colors and both "64GB" and "128 GB" sizes.
So, my question is how to achieve this?
Try use Nested Queries.
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "criteria",
"query": {
"bool": {
"must": [
{
"match": {
"criteria.name": "color"
}
}
],
"filter": [
{
"terms": {
"criteria.options": [
"Blue",
"Red"
]
}
}
]
}
}
}
},
{
"nested": {
"path": "criteria",
"query": {
"bool": {
"must": [
{
"match": {
"criteria.name": "size"
}
}
],
"filter": [
{
"terms": {
"criteria.options": [
"64GB",
"128GB"
]
}
}
]
}
}
}
}
]
}
}
}