1

The JSON that I execute the query on is as below. What should be the query if I only want to retrieve the variant (which is an array of objects) with an object which has a price of 82.00.

[
   {
      "id":"Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIyODA5MjA1MTQ4NQ==",
      "createdAt":"2017-10-23T11:05:40Z",
      "updatedAt":"2018-03-10T05:24:40Z",
      "descriptionHtml":"Et blanditiis autem. Molestiae delectus vero voluptatem libero cum. Aliquam tempore ex id sed aut excepturi facilis sunt.",
      "description":"Et blanditiis autem. Molestiae delectus vero voluptatem libero cum. Aliquam tempore ex id sed aut excepturi facilis sunt.",
      "handle":"future-proofed-re-engineered-handmade-cotton-chicken",
      "productType":"Computers",
      "title":"Future-proofed Re-engineered Handmade Cotton Chicken",
      "vendor":"Bednar LLC",
      "tags":[
         {
            "value":"data-generator"
         }
      ],
      "publishedAt":"2018-03-07T08:25:38Z",
      "onlineStoreUrl":null,
      "options":[
         {
            "id":"Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0T3B0aW9uLzM2NTQ0NDI2ODA2MQ==",
            "name":"Title",
            "values":[
               {
                  "value":"Concrete blue - 71y-9a6"
               },
               {
                  "value":"Concrete teal - oxh-g1z"
               }
            ]
         }
      ],
      "images":[

      ],
      "variants":[
         {
            "id":"Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8zMzczOTAzODcyMDI5",
            "title":"Concrete blue - 71y-9a6",
            "price":"82.00",
            "weight":14,
            "available":true,
            "sku":"",
            "compareAtPrice":null,
            "image":null,
            "selectedOptions":[
               {
                  "name":"Title",
                  "value":"Concrete blue - 71y-9a6"
               }
            ],
            "product":{
               "id":"Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIyODA5MjA1MTQ4NQ==",
               "images":[

               ]
            }
         },
         {
            "id":"Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8zMzczOTA0MDAzMTAx",
            "title":"Concrete teal - oxh-g1z",
            "price":"196.00",
            "weight":7,
            "available":true,
            "sku":"",
            "compareAtPrice":null,
            "image":null,
            "selectedOptions":[
               {
                  "name":"Title",
                  "value":"Concrete teal - oxh-g1z"
               }
            ],
            "product":{
               "id":"Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIyODA5MjA1MTQ4NQ==",
               "images":[

               ]
            }
         }
      ]
   }
]

I'm currently using the below way to index data.

var bulkIndex = function bulkIndex(index, type, data) {
    let bulkBody = [];

    data.forEach(item => {
        bulkBody.push({
            index: {
                _index: index,
                _type: type,
                _id: item.id
            }

        });

        bulkBody.push(item);
    });

    esClient.bulk({body: bulkBody})
        .then(response => {
            let errorCount = 0;
            response.items.forEach(item => {
                if (item.index && item.index.error) {
                    console.log(++errorCount, item.index.error);
                }
            });
            console.log(`Successfully indexed ${data.length - errorCount} out of ${data.length} items`);
        })
        .catch(console.err);
};

Mapping created is as follows.

{
  "shopify": {
    "mappings": {
      "products": {
        "properties": {
          "createdAt": {
            "type": "date"
          },
          "description": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "descriptionHtml": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "handle": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "id": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "images": {
            "properties": {
              "id": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "src": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              }
            }
          },
          "options": {
            "properties": {
              "id": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "name": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "values": {
                "properties": {
                  "value": {
                    "type": "text",
                    "fields": {
                      "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                      }
                    }
                  }
                }
              }
            }
          },
          "productType": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "publishedAt": {
            "type": "date"
          },
          "tags": {
            "properties": {
              "value": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              }
            }
          },
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "updatedAt": {
            "type": "date"
          },
          "variants": {
            "properties": {
              "available": {
                "type": "boolean"
              },
              "id": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "price": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "product": {
                "properties": {
                  "id": {
                    "type": "text",
                    "fields": {
                      "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                      }
                    }
                  },
                  "images": {
                    "properties": {
                      "id": {
                        "type": "text",
                        "fields": {
                          "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                          }
                        }
                      },
                      "src": {
                        "type": "text",
                        "fields": {
                          "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                          }
                        }
                      }
                    }
                  }
                }
              },
              "selectedOptions": {
                "properties": {
                  "name": {
                    "type": "text",
                    "fields": {
                      "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                      }
                    }
                  },
                  "value": {
                    "type": "text",
                    "fields": {
                      "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                      }
                    }
                  }
                }
              },
              "sku": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "title": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "weight": {
                "type": "long"
              }
            }
          },
          "vendor": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

1 Answer 1

2

As I am understanding, you want to retrieve document with variants items which has price of "82.00" i.e. variant - "Concrete blue - 71y-9a6" and not "Concrete teal - oxh-g1z" in document above.

In a regular scenario, if you search for document with variant price "82.00", it will find and return all document that match variant price and as well as other variants item in array which price is not "82.00".

{
    "query" : {
        "match":{
            "variants.price" :"82.00"
        }
    }
}

//Will return above document with variants items both "Concrete blue - 71y-9a6" and "Concrete teal - oxh-g1z". 

However, if you want to retrieve only variant item with price "82.00", you need to able to query that variant item separately and the solution is to use nested datatype in your doucument mapping.

The nested type is a specialized version of the object datatype that allows arrays of objects to be indexed and queried independently of each other.

{
  "mappings": {
    "foo": {
      "properties": {
        "createdAt": {
          "type": "date"
        },
        "description": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "descriptionHtml": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "handle": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "id": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "options": {
          "properties": {
            "id": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "name": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "values": {
              "properties": {
                "value": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }
              }
            }
          }
        },
        "productType": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "publishedAt": {
          "type": "date"
        },
        "tags": {
          "properties": {
            "value": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        "title": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "updatedAt": {
          "type": "date"
        },
        "variants": {
          "type": "nested",
          "properties": {
            "available": {
              "type": "boolean"
            },
            "id": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "price": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "product": {
              "properties": {
                "id": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }
              }
            },
            "selectedOptions": {
              "properties": {
                "name": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "value": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }
              }
            },
            "sku": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "title": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "weight": {
              "type": "long"
            }
          }
        },
        "vendor": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

Querying your document:

{
  "query": {
    "nested": {
      "path": "variants",
      "query": {
        "match": {
          "variants.price": "82.00"
        }
      },
      "inner_hits": {}
    }
  }
}

In above query, the variants nested field is explicitly queried with variant price "82.00". Note that, inner_hits allow us to highlight the matching nested documents because, elastic return the complete document along with all variant items, the inner_hits will contains only matched variant item (this is what we need). Also, you can limit field projection with _source (e.g. you may not want variants field root document but only variant items in inner_hits).

{
  "took": 45,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.6931472,
    "hits": [
      {
        "_index": "foo",
        "_type": "foo",
        "_id": "1",
        "_score": 0.6931472,
        "_source": {
          "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIyODA5MjA1MTQ4NQ==",
          "createdAt": "2017-10-23T11:05:40Z",
          "updatedAt": "2018-03-10T05:24:40Z",
          "descriptionHtml": "Et blanditiis autem. Molestiae delectus vero voluptatem libero cum. Aliquam tempore ex id sed aut excepturi facilis sunt.",
          "description": "Et blanditiis autem. Molestiae delectus vero voluptatem libero cum. Aliquam tempore ex id sed aut excepturi facilis sunt.",
          "handle": "future-proofed-re-engineered-handmade-cotton-chicken",
          "productType": "Computers",
          "title": "Future-proofed Re-engineered Handmade Cotton Chicken",
          "vendor": "Bednar LLC",
          "tags": [
            {
              "value": "data-generator"
            }
          ],
          "publishedAt": "2018-03-07T08:25:38Z",
          "onlineStoreUrl": null,
          "options": [
            {
              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0T3B0aW9uLzM2NTQ0NDI2ODA2MQ==",
              "name": "Title",
              "values": [
                {
                  "value": "Concrete blue - 71y-9a6"
                },
                {
                  "value": "Concrete teal - oxh-g1z"
                }
              ]
            }
          ],
          "images": [],
          "variants": [
            {
              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8zMzczOTAzODcyMDI5",
              "title": "Concrete blue - 71y-9a6",
              "price": "82.00",
              "weight": 14,
              "available": true,
              "sku": "",
              "compareAtPrice": null,
              "image": null,
              "selectedOptions": [
                {
                  "name": "Title",
                  "value": "Concrete blue - 71y-9a6"
                }
              ],
              "product": {
                "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIyODA5MjA1MTQ4NQ==",
                "images": []
              }
            },
            {
              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8zMzczOTA0MDAzMTAx",
              "title": "Concrete teal - oxh-g1z",
              "price": "196.00",
              "weight": 7,
              "available": true,
              "sku": "",
              "compareAtPrice": null,
              "image": null,
              "selectedOptions": [
                {
                  "name": "Title",
                  "value": "Concrete teal - oxh-g1z"
                }
              ],
              "product": {
                "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIyODA5MjA1MTQ4NQ==",
                "images": []
              }
            }
          ]
        },
        "inner_hits": {
          "variants": {
            "hits": {
              "total": 1,
              "max_score": 0.6931472,
              "hits": [
                {
                  "_nested": {
                    "field": "variants",
                    "offset": 0
                  },
                  "_score": 0.6931472,
                  "_source": {
                    "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8zMzczOTAzODcyMDI5",
                    "title": "Concrete blue - 71y-9a6",
                    "price": "82.00",
                    "weight": 14,
                    "available": true,
                    "sku": "",
                    "compareAtPrice": null,
                    "image": null,
                    "selectedOptions": [
                      {
                        "name": "Title",
                        "value": "Concrete blue - 71y-9a6"
                      }
                    ],
                    "product": {
                      "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIyODA5MjA1MTQ4NQ==",
                      "images": []
                    }
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}
Sign up to request clarification or add additional context in comments.

10 Comments

Was about to write a similar answer. Is there actually another way that this could be achieved, the filtering of the nested objects?
There could be, but currently I am aware of this approach only.
@RaKa Awesome explanation! I tried running the query that you have mentioned under Querying your document. However, on executing it, I'm getting illegal_state_exception. "reason": "[nested] nested object under path [variants] is not of nested type"
you have to be careful with the type of the index that you declare in your mappings. In this case "mappings" : {"foo",.... you have to query like PUT your_index/foo/your_id
@EiriniGraonidou I'm using bulk indexing API. I've edited my question.
|

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.