検索結果の折りたたみ

フィールド値に基づいて検索結果を折りたたむには、collapseパラメータを使用できます。折りたたみは、各折りたたみキーごとに上位のソートされたドキュメントのみを選択することによって行われます。

たとえば、次の検索はuser.idで結果を折りたたみ、http.response.bytesでソートします。

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. query={
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. collapse={
  9. "field": "user.id"
  10. },
  11. sort=[
  12. {
  13. "http.response.bytes": {
  14. "order": "desc"
  15. }
  16. }
  17. ],
  18. from_=0,
  19. )
  20. print(resp)

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. query: {
  4. match: {
  5. message: "GET /search",
  6. },
  7. },
  8. collapse: {
  9. field: "user.id",
  10. },
  11. sort: [
  12. {
  13. "http.response.bytes": {
  14. order: "desc",
  15. },
  16. },
  17. ],
  18. from: 0,
  19. });
  20. console.log(response);

コンソール

  1. GET my-index-000001/_search
  2. {
  3. "query": {
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. "collapse": {
  9. "field": "user.id"
  10. },
  11. "sort": [
  12. {
  13. "http.response.bytes": {
  14. "order": "desc"
  15. }
  16. }
  17. ],
  18. "from": 0
  19. }
user.idフィールドを使用して結果セットを折りたたむ
http.response.bytesで結果をソートする
最初の折りたたまれた結果のオフセットを定義する

レスポンス内のヒットの総数は、折りたたみなしで一致するドキュメントの数を示します。異なるグループの総数は不明です。

折りたたみに使用されるフィールドは、単一値のkeywordまたはnumericフィールドで、doc_valuesが有効になっている必要があります。

折りたたみは上位のヒットのみに適用され、集計には影響しません。

折りたたみ結果の展開

inner hitsオプションを使用して、各折りたたまれた上位ヒットを展開することも可能です。

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. query={
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. collapse={
  9. "field": "user.id",
  10. "inner_hits": {
  11. "name": "most_recent",
  12. "size": 5,
  13. "sort": [
  14. {
  15. "@timestamp": "desc"
  16. }
  17. ]
  18. },
  19. "max_concurrent_group_searches": 4
  20. },
  21. sort=[
  22. {
  23. "http.response.bytes": {
  24. "order": "desc"
  25. }
  26. }
  27. ],
  28. )
  29. print(resp)

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. query: {
  4. match: {
  5. message: "GET /search",
  6. },
  7. },
  8. collapse: {
  9. field: "user.id",
  10. inner_hits: {
  11. name: "most_recent",
  12. size: 5,
  13. sort: [
  14. {
  15. "@timestamp": "desc",
  16. },
  17. ],
  18. },
  19. max_concurrent_group_searches: 4,
  20. },
  21. sort: [
  22. {
  23. "http.response.bytes": {
  24. order: "desc",
  25. },
  26. },
  27. ],
  28. });
  29. console.log(response);

コンソール

  1. GET /my-index-000001/_search
  2. {
  3. "query": {
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. "collapse": {
  9. "field": "user.id",
  10. "inner_hits": {
  11. "name": "most_recent",
  12. "size": 5,
  13. "sort": [ { "@timestamp": "desc" } ]
  14. },
  15. "max_concurrent_group_searches": 4
  16. },
  17. "sort": [
  18. {
  19. "http.response.bytes": {
  20. "order": "desc"
  21. }
  22. }
  23. ]
  24. }
user.idフィールドを使用して結果セットを折りたたむ
レスポンス内のインナーヒットセクションに使用される名前
各折りたたみキーごとに取得するinner_hitsの数
各グループ内のドキュメントをソートする方法
各グループごとにinner_hitsを取得するために許可される同時リクエストの数

サポートされているオプションの完全なリストとレスポンスの形式については、インナーヒットを参照してください。

各折りたたまれたヒットに対して複数のinner hitsをリクエストすることも可能です。これは、折りたたまれたヒットの複数の表現を取得したい場合に便利です。

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. query={
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. collapse={
  9. "field": "user.id",
  10. "inner_hits": [
  11. {
  12. "name": "largest_responses",
  13. "size": 3,
  14. "sort": [
  15. {
  16. "http.response.bytes": {
  17. "order": "desc"
  18. }
  19. }
  20. ]
  21. },
  22. {
  23. "name": "most_recent",
  24. "size": 3,
  25. "sort": [
  26. {
  27. "@timestamp": {
  28. "order": "desc"
  29. }
  30. }
  31. ]
  32. }
  33. ]
  34. },
  35. sort=[
  36. "http.response.bytes"
  37. ],
  38. )
  39. print(resp)

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. query: {
  4. match: {
  5. message: "GET /search",
  6. },
  7. },
  8. collapse: {
  9. field: "user.id",
  10. inner_hits: [
  11. {
  12. name: "largest_responses",
  13. size: 3,
  14. sort: [
  15. {
  16. "http.response.bytes": {
  17. order: "desc",
  18. },
  19. },
  20. ],
  21. },
  22. {
  23. name: "most_recent",
  24. size: 3,
  25. sort: [
  26. {
  27. "@timestamp": {
  28. order: "desc",
  29. },
  30. },
  31. ],
  32. },
  33. ],
  34. },
  35. sort: ["http.response.bytes"],
  36. });
  37. console.log(response);

コンソール

  1. GET /my-index-000001/_search
  2. {
  3. "query": {
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. "collapse": {
  9. "field": "user.id",
  10. "inner_hits": [
  11. {
  12. "name": "largest_responses",
  13. "size": 3,
  14. "sort": [
  15. {
  16. "http.response.bytes": {
  17. "order": "desc"
  18. }
  19. }
  20. ]
  21. },
  22. {
  23. "name": "most_recent",
  24. "size": 3,
  25. "sort": [
  26. {
  27. "@timestamp": {
  28. "order": "desc"
  29. }
  30. }
  31. ]
  32. }
  33. ]
  34. },
  35. "sort": [
  36. "http.response.bytes"
  37. ]
  38. }
user.idフィールドを使用して結果セットを折りたたむ
ユーザーのために3つの最大HTTPレスポンスを返す
ユーザーのために3つの最新のHTTPレスポンスを返す

グループの展開は、レスポンスで返された各折りたたまれたヒットに対してinner_hitリクエストごとに追加のクエリを送信することによって行われます。グループやinner_hitリクエストが多すぎると、検索が大幅に遅くなる可能性があります。

  1. [`````collapse`````]は[スクロール](238327401f76c2ac.md#scroll-search-results)と併用することはできません。
  2. ## search_afterによる折りたたみ
  3. フィールドの折りたたみは、[`````search_after`````](238327401f76c2ac.md#search-after)パラメータと一緒に使用できます。`````search_after`````を使用するのは、同じフィールドでソートおよび折りたたみを行う場合のみサポートされています。二次ソートも許可されていません。たとえば、`````user.id`````で折りたたみおよびソートし、`````search_after`````を使用して結果をページングできます:
  4. #### Python
  5. ``````python
  6. resp = client.search(
  7. index="my-index-000001",
  8. query={
  9. "match": {
  10. "message": "GET /search"
  11. }
  12. },
  13. collapse={
  14. "field": "user.id"
  15. },
  16. sort=[
  17. "user.id"
  18. ],
  19. search_after=[
  20. "dd5ce1ad"
  21. ],
  22. )
  23. print(resp)
  24. `

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. query: {
  4. match: {
  5. message: "GET /search",
  6. },
  7. },
  8. collapse: {
  9. field: "user.id",
  10. },
  11. sort: ["user.id"],
  12. search_after: ["dd5ce1ad"],
  13. });
  14. console.log(response);

コンソール

  1. GET /my-index-000001/_search
  2. {
  3. "query": {
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. "collapse": {
  9. "field": "user.id"
  10. },
  11. "sort": [ "user.id" ],
  12. "search_after": ["dd5ce1ad"]
  13. }

折りたたみ結果の再スコアリング

rescore検索パラメータとともにフィールドの折りたたみを使用できます。再スコアラーは、折りたたみフィールドごとの上位ランクのドキュメントに対して各シャードで実行されます。信頼できる順序を維持するために、同じ折りたたみフィールド値を共有するドキュメントを1つのシャードにクラスタリングすることをお勧めします。これは、インデックス作成時に折りたたみフィールド値をルーティングキーとして割り当てることによって実現されます:

Python

  1. resp = client.index(
  2. index="my-index-000001",
  3. routing="xyz",
  4. document={
  5. "@timestamp": "2099-11-15T13:12:00",
  6. "message": "You know for search!",
  7. "user.id": "xyz"
  8. },
  9. )
  10. print(resp)

Js

  1. const response = await client.index({
  2. index: "my-index-000001",
  3. routing: "xyz",
  4. document: {
  5. "@timestamp": "2099-11-15T13:12:00",
  6. message: "You know for search!",
  7. "user.id": "xyz",
  8. },
  9. });
  10. console.log(response);

コンソール

  1. POST /my-index-000001/_doc?routing=xyz
  2. {
  3. "@timestamp": "2099-11-15T13:12:00",
  4. "message": "You know for search!",
  5. "user.id": "xyz"
  6. }
折りたたみフィールド値でルーティングを割り当てる(user.id)。

これにより、折りたたみキーごとに1つの上位ドキュメントのみがグローバルに再スコアリングされることが保証されます。

次のリクエストは、user.idフィールドでフィールドの折りたたみを利用し、次にクエリ再スコアラーで上位グループを再スコアリングします:

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. query={
  4. "match": {
  5. "message": "you know for search"
  6. }
  7. },
  8. collapse={
  9. "field": "user.id"
  10. },
  11. rescore={
  12. "window_size": 50,
  13. "query": {
  14. "rescore_query": {
  15. "match_phrase": {
  16. "message": "you know for search"
  17. }
  18. },
  19. "query_weight": 0.3,
  20. "rescore_query_weight": 1.4
  21. }
  22. },
  23. )
  24. print(resp)

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. query: {
  4. match: {
  5. message: "you know for search",
  6. },
  7. },
  8. collapse: {
  9. field: "user.id",
  10. },
  11. rescore: {
  12. window_size: 50,
  13. query: {
  14. rescore_query: {
  15. match_phrase: {
  16. message: "you know for search",
  17. },
  18. },
  19. query_weight: 0.3,
  20. rescore_query_weight: 1.4,
  21. },
  22. },
  23. });
  24. console.log(response);

コンソール

  1. GET /my-index-000001/_search
  2. {
  3. "query": {
  4. "match": {
  5. "message": "you know for search"
  6. }
  7. },
  8. "collapse": {
  9. "field": "user.id"
  10. },
  11. "rescore" : {
  12. "window_size" : 50,
  13. "query" : {
  14. "rescore_query" : {
  15. "match_phrase": {
  16. "message": "you know for search"
  17. }
  18. },
  19. "query_weight" : 0.3,
  20. "rescore_query_weight" : 1.4
  21. }
  22. }
  23. }

再スコアラーはinner hitsには適用されません。

第二レベルの折りたたみ

第二レベルの折りたたみもサポートされており、inner_hitsに適用されます。

たとえば、次の検索はgeo.country_nameで結果を折りたたみます。各geo.country_name内で、インナーヒットはuser.idで折りたたまれます。

第二レベルの折りたたみではinner_hitsは許可されません。

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. query={
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. collapse={
  9. "field": "geo.country_name",
  10. "inner_hits": {
  11. "name": "by_location",
  12. "collapse": {
  13. "field": "user.id"
  14. },
  15. "size": 3
  16. }
  17. },
  18. )
  19. print(resp)

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. query: {
  4. match: {
  5. message: "GET /search",
  6. },
  7. },
  8. collapse: {
  9. field: "geo.country_name",
  10. inner_hits: {
  11. name: "by_location",
  12. collapse: {
  13. field: "user.id",
  14. },
  15. size: 3,
  16. },
  17. },
  18. });
  19. console.log(response);

コンソール

  1. GET /my-index-000001/_search
  2. {
  3. "query": {
  4. "match": {
  5. "message": "GET /search"
  6. }
  7. },
  8. "collapse": {
  9. "field": "geo.country_name",
  10. "inner_hits": {
  11. "name": "by_location",
  12. "collapse": { "field": "user.id" },
  13. "size": 3
  14. }
  15. }
  16. }

コンソール-結果

  1. {
  2. "hits" : {
  3. "hits" : [
  4. {
  5. "_index" : "my-index-000001",
  6. "_id" : "oX9uXXoB0da05OCR3adK",
  7. "_score" : 0.5753642,
  8. "_source" : {
  9. "@timestamp" : "2099-11-15T14:12:12",
  10. "geo" : {
  11. "country_name" : "Amsterdam"
  12. },
  13. "http" : {
  14. "request" : {
  15. "method" : "get"
  16. },
  17. "response" : {
  18. "bytes" : 1070000,
  19. "status_code" : 200
  20. },
  21. "version" : "1.1"
  22. },
  23. "message" : "GET /search HTTP/1.1 200 1070000",
  24. "source" : {
  25. "ip" : "127.0.0.1"
  26. },
  27. "user" : {
  28. "id" : "kimchy"
  29. }
  30. },
  31. "fields" : {
  32. "geo.country_name" : [
  33. "Amsterdam"
  34. ]
  35. },
  36. "inner_hits" : {
  37. "by_location" : {
  38. "hits" : {
  39. "total" : {
  40. "value" : 1,
  41. "relation" : "eq"
  42. },
  43. "max_score" : 0.5753642,
  44. "hits" : [
  45. {
  46. "_index" : "my-index-000001",
  47. "_id" : "oX9uXXoB0da05OCR3adK",
  48. "_score" : 0.5753642,
  49. "_source" : {
  50. "@timestamp" : "2099-11-15T14:12:12",
  51. "geo" : {
  52. "country_name" : "Amsterdam"
  53. },
  54. "http" : {
  55. "request" : {
  56. "method" : "get"
  57. },
  58. "response" : {
  59. "bytes" : 1070000,
  60. "status_code" : 200
  61. },
  62. "version" : "1.1"
  63. },
  64. "message" : "GET /search HTTP/1.1 200 1070000",
  65. "source" : {
  66. "ip" : "127.0.0.1"
  67. },
  68. "user" : {
  69. "id" : "kimchy"
  70. }
  71. },
  72. "fields" : {
  73. "user.id" : [
  74. "kimchy"
  75. ]
  76. }
  77. }
  78. ]
  79. }
  80. }
  81. }
  82. }
  83. ]
  84. }
  85. }

スコアの追跡

collapseがフィールドでsortと共に使用されると、スコアは計算されません。track_scoresをtrueに設定すると、Elasticsearchにスコアを計算して追跡するよう指示します。