Elasticsearch neumožňuje pracovat s relacemi tak, jak jsme zvyklí z relačních databází. V této kapitole si ukážeme, jak s touto skutečností pracovat.
Předpokládejme, že máme v databázi dvě provázané tabulky — order a order_product:
order:
| id | date | status | |
|---|---|---|---|
| 1 | john.s@icloud.com | 2022-02-20 | delivered |
| 2 | jorge.c@gmail.com | 2022-02-21 | new |
order_product:
| id | order_id | name | price |
|---|---|---|---|
| 24 | 1 | OttLite Achieve Desk Lamp | 49.97 |
| 25 | 1 | TOPS Pen Pal Flexible Pen Holders | 3.36 |
| 26 | 2 | Pen+Gear Plastic Storage Box | 1.24 |
V Elasticsearch bohužel není možné provést dotaz s JOIN, který by spojil výsledky z dvou indexů.
Řešením je provést spojení ještě předtím, než se data do Elasticsearch uloží a ukládat je tak v denormalizované podobě.
Pro uložení takového dokumentu do Elasticsearch by bylo nutné vytvořit následující JSON:
xxxxxxxxxx{ "email": "john.s@icloud.com", "date": "2022-02-20", "status": "delivered", "products": [ { "name": "OttLite Achieve Desk Lamp", "price": 49.97 }, { "name": "TOPS Pen Pal Flexible Pen Holders", "price": 3.36 } ]}Přestože lze tento dokument uložit do Elasticsearch tak jak je, v některých případech se bude chovat neočekávaně.
Například, pokud zkusíme vyhledat objednávky, které obsahují produkt, jehož name začíná OttLite a zároveň je jeho price menší než 10.
V tomto případě by byl dokument nalezen, i když je první podmínka splněna jen u prvního produktu, zatímco druhá podmínka platí pouze pro druhy (odlišný) produkt.
Anychom toto chování napravili, pole products musí být typu nested:
xxxxxxxxxxPUT order_nested{ "mappings": { "properties": { "status": { "type": "keyword" }, "products": { // <= array of nested objects "type": "nested", "properties": { "price": { "type": "half_float" } } } } }}Následně při vyhledávání v nested objektu musíme i samotný dotaz zabalit do nested query:
xxxxxxxxxxGET order_nested/_search{ "query": { "nested": { "path": "products", "query": { "range": { "products.nested": { "lt": 10 } } } } }}Totéž platí pro agregace, kdy bude nutné dílčí agregace obalit speciální agregaci nested.
xxxxxxxxxxGET order_nested/_search{ "aggs": { "products_nested": { "nested": { "path": "products" }, "aggs": { "avg_price": { "avg": { "field": "products.price" } } } } }}