Elasticsearch > Pipeline > DBの中間テーブル的なパイプラインの作成3　多対多




1〜3の3です
- [Elasticsearch > Pipeline > DBの中間テーブル的なパイプラインの作成1](https://qiita.com/sugasaki/items/6b03d78fdbbb1775b719)
- [Elasticsearch > Pipeline > DBの中間テーブル的なパイプラインの作成2、データ構造をフラットにする](https://qiita.com/sugasaki/items/3d2123d160aa7e6a8812)
- [Elasticsearch > Pipeline > DBの中間テーブル的なパイプラインの作成3　多対多](https://qiita.com/sugasaki/items/10b4ab2b08248d425aa0)

---



上記は多対１のデータリレーションでしたが、多対多もやりたい事もあるでしょう。
以下のようなデータを作成します。

```
{
  "_index" : "index_a",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "index_master" : [
      {
        "master_id" : "m1",
        "master_name" : "taro",
        "master_type" : "type a"
      },
      {
        "master_id" : "m2",
        "master_name" : "jiro",
        "master_type" : "type b"
      }
    ],
    "name" : "index-data-a",
    "index_a_id" : "id1"
  }
}
```



KibanaのDevToolから進めます


まずは以下のIndexを使って進めます。
言葉の定義を以下とします。

- Master: DBのマスター的な位置付けのインデックス。
- Reference: MasterとDataIndexを紐付ける情報。DBの世界では関係テーブルと呼ばれるもの
- DataIndex: データを投入するインデックス。主に検索対象のインデックス



![Kobito.GzkH7X.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/c38a9bc1-c757-caf2-d1f9-9f6a2a614c71.png "Kobito.GzkH7X.png")


### インデックス作成

図のピンク部分のIndexを作成します。

```
# Master用のIndex作成・データ追加
POST index_master/_doc/1
{
  "master_id": "m1",
  "master_name": "taro",
  "master_type": "type a"
}
POST index_master/_doc/2
{
  "master_id": "m2",
  "master_name": "jiro",
  "master_type": "type b"
}

# Reference用のIndex作成・データ追加
POST index_cross_reference/_doc/1
{
  "index_a_id": "id1",
  "master_id": "m1"
}
POST index_cross_reference/_doc/2
{
  "index_a_id": "id1",
  "master_id": "m2"
}
```


DataIndex用のIndex作成・データ追加を行います。
図でいくと、黄色の部分です。

```
# DataIndex用のIndex作成・データ追加
PUT /index_a/_doc/1
{
  "index_a_id": "id1",
  "name": "index-data-a"
}
```


### エンリッチポリシーの作成

図の鎖線丸で囲まれた部分です

```
# index_cross_referenceに対してindex_a_idをもとに、master_idを付与する
PUT /_enrich/policy/index-cross-reference-policy
{
  "match": {
    "indices": "index_cross_reference",
    "match_field": "index_a_id",
    "enrich_fields": ["master_id"]
  }
}

# index_masterに対してmaster_idをもとに、master_nameを付与する
PUT /_enrich/policy/index-master-policy
{
  "match": {
    "indices": "index_master",
    "match_field": "master_id",
    "enrich_fields": ["master_name", "master_type"]
  }
}
```


Ingest Pipelineの作成、青枠で囲まれた部分です

foreachを使って配列形式にします


```
# Ingest Pipelineの作成
PUT /_ingest/pipeline/test-pipeline
{
  "description": "forum test",
  "processors": [
    {
      "enrich": {
        "policy_name": "index-cross-reference-policy",
        "field": "index_a_id",
        "target_field": "index_master",
        "max_matches": "100",
        "ignore_missing": true
      }
    },
    {
      "foreach": {
        "field": "index_master",
        "ignore_missing": true,
        "processor": {
          "enrich": {
            "policy_name": "index-master-policy",
            "field": "_ingest._value.master_id",
            "target_field": "_ingest._value",
            "max_matches": "1",
            "ignore_missing": true
          }
        }
      }
    }
  ]
}
```


### policyの実行（適用）

Enrich Processorは、直接index_masterやindex_cross_referenceを参照するわけではないため、Enrich用のIndex作成します

```
POST /_enrich/policy/index-cross-reference-policy/_execute
POST /_enrich/policy/index-master-policy/_execute
```


### _update_by_query


```
POST /index_a/_update_by_query?pipeline=test-pipeline
```





### 確認

```
GET /index_a/_doc/1
```


### 結果

```
{
  "_index" : "index_a",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "index_master" : [
      {
        "master_id" : "m1",
        "master_name" : "taro",
        "master_type" : "type a"
      },
      {
        "master_id" : "m2",
        "master_name" : "jiro",
        "master_type" : "type b"
      }
    ],
    "name" : "index-data-a",
    "index_a_id" : "id1"
  }
}
```



### データ更新

```
# Master用のデータ更新
POST index_master/_doc/1
{
  "master_id": "m2",
  "master_name": "jack",
  "master_type": "type b"
}
```


#### ポリシーの実行

```
POST /_enrich/policy/index-cross-reference-policy/_execute
POST /_enrich/policy/index-master-policy/_execute
```

#### パイプライン適用・データ更新

```
POST /index_a/_update_by_query?pipeline=test-pipeline
```



### 結果

```
{
  "_index" : "index_a",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 4,
  "_seq_no" : 3,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "index_master" : [
      {
        "master_id" : "m1",
        "master_name" : "taro",
        "master_type" : "type a"
      },
      {
        "master_id" : "m2",
        "master_name" : "jack",
        "master_type" : "type b"
      }
    ],
    "name" : "index-data-a",
    "index_a_id" : "id1"
  }
}

```



# 参考

[【ingest node】別のindexのデータを登録する方法について \- Elastic In Your Native Tongue / 日本語による質問・議論はこちら \- Discuss the Elastic Stack](https://discuss.elastic.co/t/ingest-node-index/245375)


[Reindexが登場\! \| Elastic Blog](https://www.elastic.co/jp/blog/reindex-is-coming)