ネストされた集約

ネストされたドキュメントを集約するための特別な単一バケット集約です。

例えば、製品のインデックスがあり、各製品がリセラーのリストを保持しているとしましょう - 各リセラーは製品の価格を持っています。マッピングは次のようになります:

Python

  1. resp = client.indices.create(
  2. index="products",
  3. mappings={
  4. "properties": {
  5. "resellers": {
  6. "type": "nested",
  7. "properties": {
  8. "reseller": {
  9. "type": "keyword"
  10. },
  11. "price": {
  12. "type": "double"
  13. }
  14. }
  15. }
  16. }
  17. },
  18. )
  19. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'products',
  3. body: {
  4. mappings: {
  5. properties: {
  6. resellers: {
  7. type: 'nested',
  8. properties: {
  9. reseller: {
  10. type: 'keyword'
  11. },
  12. price: {
  13. type: 'double'
  14. }
  15. }
  16. }
  17. }
  18. }
  19. }
  20. )
  21. puts response

Js

  1. const response = await client.indices.create({
  2. index: "products",
  3. mappings: {
  4. properties: {
  5. resellers: {
  6. type: "nested",
  7. properties: {
  8. reseller: {
  9. type: "keyword",
  10. },
  11. price: {
  12. type: "double",
  13. },
  14. },
  15. },
  16. },
  17. },
  18. });
  19. console.log(response);

コンソール

  1. PUT /products
  2. {
  3. "mappings": {
  4. "properties": {
  5. "resellers": {
  6. "type": "nested",
  7. "properties": {
  8. "reseller": {
  9. "type": "keyword"
  10. },
  11. "price": {
  12. "type": "double"
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }
resellers はネストされたドキュメントを保持する配列です。

次のリクエストは、2つのリセラーを持つ製品を追加します:

Python

  1. resp = client.index(
  2. index="products",
  3. id="0",
  4. refresh=True,
  5. document={
  6. "name": "LED TV",
  7. "resellers": [
  8. {
  9. "reseller": "companyA",
  10. "price": 350
  11. },
  12. {
  13. "reseller": "companyB",
  14. "price": 500
  15. }
  16. ]
  17. },
  18. )
  19. print(resp)

Ruby

  1. response = client.index(
  2. index: 'products',
  3. id: 0,
  4. refresh: true,
  5. body: {
  6. name: 'LED TV',
  7. resellers: [
  8. {
  9. reseller: 'companyA',
  10. price: 350
  11. },
  12. {
  13. reseller: 'companyB',
  14. price: 500
  15. }
  16. ]
  17. }
  18. )
  19. puts response

Js

  1. const response = await client.index({
  2. index: "products",
  3. id: 0,
  4. refresh: "true",
  5. document: {
  6. name: "LED TV",
  7. resellers: [
  8. {
  9. reseller: "companyA",
  10. price: 350,
  11. },
  12. {
  13. reseller: "companyB",
  14. price: 500,
  15. },
  16. ],
  17. },
  18. });
  19. console.log(response);

コンソール

  1. PUT /products/_doc/0?refresh
  2. {
  3. "name": "LED TV",
  4. "resellers": [
  5. {
  6. "reseller": "companyA",
  7. "price": 350
  8. },
  9. {
  10. "reseller": "companyB",
  11. "price": 500
  12. }
  13. ]
  14. }
name 属性に対して動的マッピングを使用しています。

次のリクエストは、製品が購入できる最小価格を返します:

Python

  1. resp = client.search(
  2. index="products",
  3. size="0",
  4. query={
  5. "match": {
  6. "name": "led tv"
  7. }
  8. },
  9. aggs={
  10. "resellers": {
  11. "nested": {
  12. "path": "resellers"
  13. },
  14. "aggs": {
  15. "min_price": {
  16. "min": {
  17. "field": "resellers.price"
  18. }
  19. }
  20. }
  21. }
  22. },
  23. )
  24. print(resp)

Ruby

  1. response = client.search(
  2. index: 'products',
  3. size: 0,
  4. body: {
  5. query: {
  6. match: {
  7. name: 'led tv'
  8. }
  9. },
  10. aggregations: {
  11. resellers: {
  12. nested: {
  13. path: 'resellers'
  14. },
  15. aggregations: {
  16. min_price: {
  17. min: {
  18. field: 'resellers.price'
  19. }
  20. }
  21. }
  22. }
  23. }
  24. }
  25. )
  26. puts response

Js

  1. const response = await client.search({
  2. index: "products",
  3. size: 0,
  4. query: {
  5. match: {
  6. name: "led tv",
  7. },
  8. },
  9. aggs: {
  10. resellers: {
  11. nested: {
  12. path: "resellers",
  13. },
  14. aggs: {
  15. min_price: {
  16. min: {
  17. field: "resellers.price",
  18. },
  19. },
  20. },
  21. },
  22. },
  23. });
  24. console.log(response);

コンソール

  1. GET /products/_search?size=0
  2. {
  3. "query": {
  4. "match": {
  5. "name": "led tv"
  6. }
  7. },
  8. "aggs": {
  9. "resellers": {
  10. "nested": {
  11. "path": "resellers"
  12. },
  13. "aggs": {
  14. "min_price": {
  15. "min": {
  16. "field": "resellers.price"
  17. }
  18. }
  19. }
  20. }
  21. }
  22. }

上記のように、ネストされた集約は、最上位のドキュメント内のネストされたドキュメントの path を必要とします。これにより、これらのネストされたドキュメントに対して任意のタイプの集約を定義できます。

レスポンス:

コンソール-結果

  1. {
  2. ...
  3. "aggregations": {
  4. "resellers": {
  5. "doc_count": 2,
  6. "min_price": {
  7. "value": 350.0
  8. }
  9. }
  10. }
  11. }

特定のリセラーの結果を返すために、filter サブ集約を使用できます。

Python

  1. resp = client.search(
  2. index="products",
  3. size="0",
  4. query={
  5. "match": {
  6. "name": "led tv"
  7. }
  8. },
  9. aggs={
  10. "resellers": {
  11. "nested": {
  12. "path": "resellers"
  13. },
  14. "aggs": {
  15. "filter_reseller": {
  16. "filter": {
  17. "bool": {
  18. "filter": [
  19. {
  20. "term": {
  21. "resellers.reseller": "companyB"
  22. }
  23. }
  24. ]
  25. }
  26. },
  27. "aggs": {
  28. "min_price": {
  29. "min": {
  30. "field": "resellers.price"
  31. }
  32. }
  33. }
  34. }
  35. }
  36. }
  37. },
  38. )
  39. print(resp)

Ruby

  1. response = client.search(
  2. index: 'products',
  3. size: 0,
  4. body: {
  5. query: {
  6. match: {
  7. name: 'led tv'
  8. }
  9. },
  10. aggregations: {
  11. resellers: {
  12. nested: {
  13. path: 'resellers'
  14. },
  15. aggregations: {
  16. filter_reseller: {
  17. filter: {
  18. bool: {
  19. filter: [
  20. {
  21. term: {
  22. 'resellers.reseller' => 'companyB'
  23. }
  24. }
  25. ]
  26. }
  27. },
  28. aggregations: {
  29. min_price: {
  30. min: {
  31. field: 'resellers.price'
  32. }
  33. }
  34. }
  35. }
  36. }
  37. }
  38. }
  39. }
  40. )
  41. puts response

Js

  1. const response = await client.search({
  2. index: "products",
  3. size: 0,
  4. query: {
  5. match: {
  6. name: "led tv",
  7. },
  8. },
  9. aggs: {
  10. resellers: {
  11. nested: {
  12. path: "resellers",
  13. },
  14. aggs: {
  15. filter_reseller: {
  16. filter: {
  17. bool: {
  18. filter: [
  19. {
  20. term: {
  21. "resellers.reseller": "companyB",
  22. },
  23. },
  24. ],
  25. },
  26. },
  27. aggs: {
  28. min_price: {
  29. min: {
  30. field: "resellers.price",
  31. },
  32. },
  33. },
  34. },
  35. },
  36. },
  37. },
  38. });
  39. console.log(response);

コンソール

  1. GET /products/_search?size=0
  2. {
  3. "query": {
  4. "match": {
  5. "name": "led tv"
  6. }
  7. },
  8. "aggs": {
  9. "resellers": {
  10. "nested": {
  11. "path": "resellers"
  12. },
  13. "aggs": {
  14. "filter_reseller": {
  15. "filter": {
  16. "bool": {
  17. "filter": [
  18. {
  19. "term": {
  20. "resellers.reseller": "companyB"
  21. }
  22. }
  23. ]
  24. }
  25. },
  26. "aggs": {
  27. "min_price": {
  28. "min": {
  29. "field": "resellers.price"
  30. }
  31. }
  32. }
  33. }
  34. }
  35. }
  36. }
  37. }

検索結果は:

コンソール-結果

  1. {
  2. ...
  3. "aggregations": {
  4. "resellers": {
  5. "doc_count": 2,
  6. "filter_reseller": {
  7. "doc_count": 1,
  8. "min_price": {
  9. "value": 500.0
  10. }
  11. }
  12. }
  13. }
  14. }