LoginSignup
3
0

More than 1 year has passed since last update.

Lookup Runtime Field 〜Elasticsearch 8.2 新機能〜

Last updated at Posted at 2022-06-20

今回紹介する機能はElasticsearch 8.2ではTechnical Previewとしてのリリースです。将来変更となる可能性があります。

Lookup Runtime Fieldとは?

Elasticsearch 8.2新機能の一つであるLookup Runtime Fieldは、これまでもEnrich Policy + Ingest Pipelineで行っていた機能をRuntime Fieldで行えるようにしたものです。
Lookup自体はご存知の方が多いと思いますが、下記のように別のIndexから同じKeyを持つ別のFieldの値をとってくることです。
公式のドキュメントはこちら
スクリーンショット 2022-06-15 12.08.45.png

この例だと、Google Driveにアクセスしている社員を知りたいがログに社員氏名は当然記録されていないので、PC_name/host.nameをKeyにして資産管理DBから氏名を取ってくる、というものです。

環境作成

それでは実際に試してみましょう
Elasticsearchの環境が必要ですので、以下のリンクの手順に従ってまずはデプロイメントを作成してみてください。
Elastic Cloud について 〜実際にデプロイメントを作ってみよう〜

Dev Tools

デプロイメントが作成できたら早速Kibanaにアクセスして、Management -> Dev Toolsをクリックしましょう。
下図のような画面が開きます。
左側にクエリを記入して実行すると右側に結果が表示されます。
スクリーンショット 2022-06-14 18.07.34.png

テスト用のインデックスを作成

上の図にあるようなインデックスを作成します。
Dev Toolsの左側にコピーして実行(Mac: Command+Enter / Win: Ctrl+Enter)

Lookup用の資産管理DB

PUT pclist/_bulk
{ "index" : {} }
{"PC_name":"aaaa1","employee_name":"田中太郎"}
{ "index" : {} }
{"PC_name":"bbbb1","employee_name":"鈴木花子"}

アクセスログ

PUT accesslog/_bulk
{ "index" : {} }
{"host.name":"aaaa1","access_to":"Google Drive"}
{ "index" : {} }
{"host.name":"bbbb1","access_to":"Qiita Web Site"}

_bulk APIは複数のデータをまとめて投入したい時に重宝するAPIです。
興味のある方はこちらを是非ご覧ください。
_bulk APIのドキュメント

検索してみよう!

それではGoogle Driveにアクセスしている社員をアクセスログから検索して表示してみましょう。
以下のクエリをDev Toolsで実行します。

GET accesslog/_search
{
  "runtime_mappings": {
    "emp_name": {
      "type": "lookup",
      "target_index": "pclist", 
      "input_field": "host.name", 
      "target_field": "PC_name", 
      "fetch_fields": ["employee_name"]
    }
  }, 
  "query": {"match": {
    "access_to": "google"
  }}, 
  "fields": [
    "host.name","access_to","emp_name"
  ],
  "_source": false
}

クエリの中身

  • runtime_mappings
    accesslogには社員名のマッピングは存在しないためクエリと同時にruntimeとして作成します
    runtimeはクエリ時に作成される情報のことです。詳しくはこちら。
    runtime fieldのドキュメント
  • emp_name
    社員名を格納するフィールド名
  • "type": "lookup"
    lookupして他のインデックスを参照しに行くことを明示します。typeには他にはtextgeo_pointなどがあります。
  • "target_index": "pclist"
    lookupしに行くインデックスを指定します。今回だと資産管理DBであるpclistです
  • "input_field": "host.name"
    lookupで突合するフィールドを指定します。今回だとaccessloghost.namepc_listPC_nameと突合させますので、inputとしてhost.nameを指定します
  • "target_field": "PC_name"
    上記の説明通りです
  • "fetch_fields": ["employee_name"]
    突合した結果として参照するフィールドを指定します。複数指定できます。
  • query
    accesslogaccess_toフィールドが"google"にマッチするもの
  • fields
    結果として表示するフィールドを指定
  • "_source": false
    これを指定しないとマッチしたドキュメントのすべてのフィールドが表示されます

クエリ結果

このような結果が返ってきます

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.7549127,
    "hits" : [
      {
        "_index" : "accesslog",
        "_id" : "vuhmYYEBidyf9EvSKJLI",
        "_score" : 0.7549127,
        "fields" : {
          "emp_name" : [
            {
              "employee_name" : [
                "田中太郎"
              ]
            }
          ],
          "access_to" : [
            "Google Drive"
          ],
          "host.name" : [
            "aaaa1"
          ]
        }
      }
    ]
  }
}

accesslogインデックスには社員名は入っていませんが、aaaa1というPCを使用している社員が「田中太郎」であることをpclistから取ってきているのがわかります。

runtime mapping

検索時に毎回指定するのは面倒臭いと思われる方もいらっしゃるでしょう。そんな方には予めruntimeをmappingしておく方法もご紹介いたします。
PUT <index名>/_mappingで明示的に指定することができます。
以下をDev Toolsで実行してみましょう。

PUT accesslog/_mapping
{
  "runtime": {
    "emp_name": {
      "type": "lookup",
      "target_index": "pclist", 
      "input_field": "host.name", 
      "target_field": "PC_name", 
      "fetch_fields": ["employee_name"]
    }
  }
}

先ほどクエリ時に指定したruntime_mappingsと全く同じ内容です。
ではaccesslogのmappingはどのようになっているでしょうか?
GET accesslog/_mappingをDev Toolsで実行すると以下のような結果が得られます。

{
  "accesslog" : {
    "mappings" : {
      "runtime" : {
        "emp_name" : {
          "type" : "lookup",
          "target_index" : "pclist",
          "input_field" : "host.name",
          "target_field" : "PC_name",
          "fetch_fields" : [
            {
              "field" : "employee_name"
            }
          ]
        }
      },
      "properties" : {
        "access_to" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "host" : {
          "properties" : {
            "name" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        }
      }
    }
  }
}

properties以下は一番最初にインデックスを作成した時に自動的に作成されたものです。
runtime部分が追加されており、クエリ時にlookupが行われます。
これによりクエリ時にruntime_mappingsを指定する必要がなくなります。

注意点

同じkeyが複数ある場合、例えばaaaa1というPCの所有者情報として、現在は「田中太郎」だがその前に「佐藤一郎」が使用していてその情報が残ったまま、というケースがあてはまります。このような場合は「田中太郎」が返ってくるか「佐藤一郎」が返ってくるかはランダムです。

またlookup runtimeに対してqueryやaggregationを行えません。
上記の例ですとaccesslogに対して検索をかけるときに、emp_name.employee_nameフィールドに「田中太郎」と指定したりすることはできません。
lookup 先の値で検索したい場合は、依然として enrich processor を利用したり、 Elasticsearch に取り込む前に JSON に enrich しておく必要があります。
用途に応じてlookupとenrich processorを使い分けましょう。

まとめ

これまではEnrich Processor + Ingest Pipelineでインデックスとして作成しなければできなかったことがクエリ時に行えるようになり、データが頻繁に変更される場合にもLookupが行えるようになりました。
是非ともお試しください。

Elastic Cloud 無料トライアル

こちらからElastic Cloudの14日間無料トライアルを是非お試しください
Elastic Cloud 無料トライアル

手順は下記リンクをご参照ください
Elastic Cloud について 〜実際にデプロイメントを作ってみよう〜

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0