隣接行列の集約

隣接行列の形式を返すバケット集約[https://en.wikipedia.org/wiki/Adjacency_matrix]。リクエストは、`````filters`````集約リクエストに似た名前付きフィルター式のコレクションを提供します。レスポンスの各バケットは、交差するフィルターの行列内の非空のセルを表します。

  1. | | A | B | C |
  2. | :-- | :-- | :-- | :-- |
  3. | **A** | A | A&B | A&C |
  4. | **B** | | B | B&C |
  5. | **C** | | | C |
  6. 交差するバケット(例: `````A&C`````)は、デフォルトの区切り文字`````&`````を使用して2つのフィルター名の組み合わせでラベル付けされます。レスポンスには`````C&A`````バケットは含まれません。なぜなら、これは`````A&C`````と同じドキュメントのセットになるからです。行列は*対称*であると言われているため、半分だけを返します。これを行うために、フィルター名の文字列をソートし、常にペアのうちの最小のものを区切りの左側の値として使用します。
  7. ## 例
  8. 次の`````interactions`````集約は、`````adjacency_matrix`````を使用して、どのグループの個人がメールを交換したかを決定します。
  9. #### Python
  10. ``````python
  11. resp = client.bulk(
  12. index="emails",
  13. refresh=True,
  14. operations=[
  15. {
  16. "index": {
  17. "_id": 1
  18. }
  19. },
  20. {
  21. "accounts": [
  22. "hillary",
  23. "sidney"
  24. ]
  25. },
  26. {
  27. "index": {
  28. "_id": 2
  29. }
  30. },
  31. {
  32. "accounts": [
  33. "hillary",
  34. "donald"
  35. ]
  36. },
  37. {
  38. "index": {
  39. "_id": 3
  40. }
  41. },
  42. {
  43. "accounts": [
  44. "vladimir",
  45. "donald"
  46. ]
  47. }
  48. ],
  49. )
  50. print(resp)
  51. resp1 = client.search(
  52. index="emails",
  53. size=0,
  54. aggs={
  55. "interactions": {
  56. "adjacency_matrix": {
  57. "filters": {
  58. "grpA": {
  59. "terms": {
  60. "accounts": [
  61. "hillary",
  62. "sidney"
  63. ]
  64. }
  65. },
  66. "grpB": {
  67. "terms": {
  68. "accounts": [
  69. "donald",
  70. "mitt"
  71. ]
  72. }
  73. },
  74. "grpC": {
  75. "terms": {
  76. "accounts": [
  77. "vladimir",
  78. "nigel"
  79. ]
  80. }
  81. }
  82. }
  83. }
  84. }
  85. },
  86. )
  87. print(resp1)
  88. `

Ruby

  1. response = client.bulk(
  2. index: 'emails',
  3. refresh: true,
  4. body: [
  5. {
  6. index: {
  7. _id: 1
  8. }
  9. },
  10. {
  11. accounts: [
  12. 'hillary',
  13. 'sidney'
  14. ]
  15. },
  16. {
  17. index: {
  18. _id: 2
  19. }
  20. },
  21. {
  22. accounts: [
  23. 'hillary',
  24. 'donald'
  25. ]
  26. },
  27. {
  28. index: {
  29. _id: 3
  30. }
  31. },
  32. {
  33. accounts: [
  34. 'vladimir',
  35. 'donald'
  36. ]
  37. }
  38. ]
  39. )
  40. puts response
  41. response = client.search(
  42. index: 'emails',
  43. body: {
  44. size: 0,
  45. aggregations: {
  46. interactions: {
  47. adjacency_matrix: {
  48. filters: {
  49. "grpA": {
  50. terms: {
  51. accounts: [
  52. 'hillary',
  53. 'sidney'
  54. ]
  55. }
  56. },
  57. "grpB": {
  58. terms: {
  59. accounts: [
  60. 'donald',
  61. 'mitt'
  62. ]
  63. }
  64. },
  65. "grpC": {
  66. terms: {
  67. accounts: [
  68. 'vladimir',
  69. 'nigel'
  70. ]
  71. }
  72. }
  73. }
  74. }
  75. }
  76. }
  77. }
  78. )
  79. puts response

Js

  1. const response = await client.bulk({
  2. index: "emails",
  3. refresh: "true",
  4. operations: [
  5. {
  6. index: {
  7. _id: 1,
  8. },
  9. },
  10. {
  11. accounts: ["hillary", "sidney"],
  12. },
  13. {
  14. index: {
  15. _id: 2,
  16. },
  17. },
  18. {
  19. accounts: ["hillary", "donald"],
  20. },
  21. {
  22. index: {
  23. _id: 3,
  24. },
  25. },
  26. {
  27. accounts: ["vladimir", "donald"],
  28. },
  29. ],
  30. });
  31. console.log(response);
  32. const response1 = await client.search({
  33. index: "emails",
  34. size: 0,
  35. aggs: {
  36. interactions: {
  37. adjacency_matrix: {
  38. filters: {
  39. grpA: {
  40. terms: {
  41. accounts: ["hillary", "sidney"],
  42. },
  43. },
  44. grpB: {
  45. terms: {
  46. accounts: ["donald", "mitt"],
  47. },
  48. },
  49. grpC: {
  50. terms: {
  51. accounts: ["vladimir", "nigel"],
  52. },
  53. },
  54. },
  55. },
  56. },
  57. },
  58. });
  59. console.log(response1);

コンソール

  1. PUT emails/_bulk?refresh
  2. { "index" : { "_id" : 1 } }
  3. { "accounts" : ["hillary", "sidney"]}
  4. { "index" : { "_id" : 2 } }
  5. { "accounts" : ["hillary", "donald"]}
  6. { "index" : { "_id" : 3 } }
  7. { "accounts" : ["vladimir", "donald"]}
  8. GET emails/_search
  9. {
  10. "size": 0,
  11. "aggs" : {
  12. "interactions" : {
  13. "adjacency_matrix" : {
  14. "filters" : {
  15. "grpA" : { "terms" : { "accounts" : ["hillary", "sidney"] }},
  16. "grpB" : { "terms" : { "accounts" : ["donald", "mitt"] }},
  17. "grpC" : { "terms" : { "accounts" : ["vladimir", "nigel"] }}
  18. }
  19. }
  20. }
  21. }
  22. }

レスポンスには、各フィルターおよびフィルターの組み合わせに対するドキュメント数を持つバケットが含まれています。マッチするドキュメントがないバケットはレスポンスから除外されます。

コンソール結果

  1. {
  2. "took": 9,
  3. "timed_out": false,
  4. "_shards": ...,
  5. "hits": ...,
  6. "aggregations": {
  7. "interactions": {
  8. "buckets": [
  9. {
  10. "key":"grpA",
  11. "doc_count": 2
  12. },
  13. {
  14. "key":"grpA&grpB",
  15. "doc_count": 1
  16. },
  17. {
  18. "key":"grpB",
  19. "doc_count": 2
  20. },
  21. {
  22. "key":"grpB&grpC",
  23. "doc_count": 1
  24. },
  25. {
  26. "key":"grpC",
  27. "doc_count": 1
  28. }
  29. ]
  30. }
  31. }
  32. }

パラメータ

  • filters
  • (必須、オブジェクト) バケットを作成するために使用されるフィルター。
    1. - `````<filter>
  • separator
  • (オプション、文字列) フィルター名を連結するために使用される区切り文字。デフォルトは&です。

レスポンスボディ

  • key
  • (文字列) バケットのフィルター。バケットが複数のフィルターを使用する場合、フィルター名はseparatorを使用して連結されます。
  • doc_count
  • (整数) バケットのフィルターに一致するドキュメントの数。

使用法

この集約単独では、無向重み付きグラフを作成するために必要なすべてのデータを提供できます。しかし、date_histogramのような子集約と共に使用すると、結果は動的ネットワーク分析を実行するために必要な追加のデータレベルを提供します。ここで、時間を超えた相互作用を調査することが重要になります。

フィルター制限

N個のフィルターの場合、生成されるバケットの行列はN²/2になる可能性があり、コストがかかることがあります。サーキットブレーカー設定は、結果があまりにも多くのバケットを生成するのを防ぎ、過剰なディスクシークを避けるためにindices.query.bool.max_clause_count設定が使用されてフィルターの数を制限します。