Splunk lookupテーブル利用時の重複レコードの扱い
lookupテーブルの中に重複レコードがある時の振る舞い
表題の通りなのだけれど、そういうことした時のsplunkでの扱いが少々意外だったので、TIPSまで。
重複レコードがある場合って?
具体的には、こんなケースです。
192.168.1.1の行が2つあります。
| Group | address |
|---|---|
| Office A | 192.168.1.1 |
| Office B | 192.168.1.1 |
| Office C | 192.168.1.2 |
SQL的に考えると、addressで別テーブルと突合した場合、例えば以下のようなテーブルとjoinすると、、、
| address | useragent |
|---|---|
| 192.168.1.1 | Mozilla ... |
| 192.168.1.1 | curl ... |
| 192.168.1.2 | Mozilla ... |
こうなるはずなんですよね。
| Group | address | useragent |
|---|---|---|
| Office A | 192.168.1.1 | Mozilla ... |
| Office A | 192.168.1.1 | curl ... |
| Office B | 192.168.1.1 | Mozilla ... |
| Office B | 192.168.1.1 | curl ... |
| Office C | 192.168.1.2 | Mozilla ... |
Splunkのlookupを使うとそうはならん、という話です。
SplunkのLookupで同じことをすると、、?
以下のように、<search>の部分でGroup-addressのテーブルを作り、lookupで読み込んだaddress-useragentのテーブルと結合すると、、、
<search (Group-address)>
| lookup (address-useragent) address
こーなる。
| Group | address | useragent |
|---|---|---|
| Office A | 192.168.1.1 | Mozilla ..., curl ... |
| Office B | 192.168.1.1 | Mozilla ..., curl ... |
| Office C | 192.168.1.2 | Mozilla ... |
lookup側からとってきた要素(useragent)について、addressが同じものはmultivalueとして束ねた上で結合されるんですね。。
Lookup結合の厄介なケース
上記のようなシンプルなケースなら、処理後にmvexpand useragenとすれば、SQLの時と同じ、1行1データの形式に変換できます。
ただ厄介なのが、lookupから持ってくる要素が複数ある場合。
例えば、、
| Group | address | useragent | priority |
|---|---|---|---|
| Office A | 192.168.1.1 | Mozilla ..., curl ... | High, Low |
| Office B | 192.168.1.1 | Mozilla ..., curl ... | High, Low |
| Office C | 192.168.1.2 | Mozilla ... | High |
これをmvexpand useragentすると、、、
| Group | address | useragent | priority |
|---|---|---|---|
| Office A | 192.168.1.1 | Mozilla ... | High, Low |
| Office A | 192.168.1.1 | curl ... | High, Low |
| Office B | 192.168.1.1 | Mozilla... | High, Low |
| Office B | 192.168.1.1 | curl ... | High, Low |
| Office C | 192.168.1.2 | Mozilla ... | High |
えぇぇ、、、、
じゃぁmvexpand useragent | mvexpand priorityとすると、、
| Group | address | useragent | priority |
|---|---|---|---|
| Office A | 192.168.1.1 | Mozilla ... | High |
| Office A | 192.168.1.1 | Mozilla ... | Low |
| Office A | 192.168.1.1 | curl ... | High |
| Office A | 192.168.1.1 | curl ... | Low |
| Office B | 192.168.1.1 | Mozilla | High |
| Office B | 192.168.1.1 | Mozilla | Low |
| Office B | 192.168.1.1 | curl ... | High |
| Office B | 192.168.1.1 | curl ... | Low |
| Office C | 192.168.1.2 | Mozilla ... | High |
。。。うん、わかってた。。
一応、eval description=mvzip(useragent, priority, "-") | mvexpand descriptionとすれば、意図に近いことはできるのだけど、そうじゃないんだよな。。。
| Group | address | description |
|---|---|---|
| Office A | 192.168.1.1 | Mozilla ...-High |
| Office A | 192.168.1.1 | curl ...-Low |
| Office B | 192.168.1.1 | Mozilla ...-High |
| Office B | 192.168.1.1 | curl ...-Low |
| Office C | 192.168.1.2 | Mozilla ...-High |
備考 join処理としてみた時の振る舞い
Left outer joinです。
元のserchの結果(上記だと、Group-address)側がLeft。
引数で制御はできないようですので、right outer join相当にしようとすると、かなり泥臭い方法をとらないといけなくなる。。。
inner join化も泥臭行っちゃ泥臭いですが、where NOT isnull(Rightにしかないfield)を挟めばinner相当のデータに絞り込めます。
まとめ
正しいやり方があるんじゃなかろうかという気はしつつも、現状は思いつかず。
Discussion