あるフィールドに用意したキーワードが含まれるレコードを取得したいことがよくあると思います。
Apache Pig でそれを実現する方法を記事にまとめました。
前提
- Python で 辞書を読み込んで Pig テンプレートに埋め込みます。
辞書
- このようにキーワードが羅列されているとします。
keywords.tsv
Hoge
Fuga
Piyo
辞書を当てる方法
手順は以下のようになります。
①辞書を 1 行に変換する
②Pig テンプレートに 1 行変換した辞書を埋め込む
①辞書を 1 行に変換する
- キーワードを OR で当てるために辞書を読み込み, 1 行に変換します。
keywords_as_one_line = load_dictionary_as_one_line('keywords.tsv', '|')
def load_dictionary_as_one_line(dictionary_file, separator):
with open(dictionary_file) as f:
lines_one_str = ''
# a\nb\nc\n -> a|b|c|d
lines = f.readlines()
for line in lines:
word = line.rstrip(os.linesep)
if(word != ''):
lines_one_str += word + separator
return lines_one_str[:-1]
②Pig テンプレートに 1 行変換した辞書を埋め込む
- Pig テンプレートに1行に変換した辞書を埋め込みます。
COND = {
'$KEYWORDS': f'.*({keywords_as_one_line}).*',
}_
translate_pig('extract_text_template.pig', 'extract_text.pig', COND)
def translate_pig(template: str, output: str, d: {str, str}):
for i, (k, v) in enumerate(d.items()):
if i == 0:
substitute_condition(template, output, k, v)
else:
substitute_condition(output, output, k, v)
return 0
変換前 Pig
CANDIDATES = FOREACH Data GENERATE
(CASE
WHEN text matches '$KEYWORDS' THEN 1
ELSE 0
END) AS flag:int;
変換後 Pig
- この例では
text
に matches で辞書のキーワードが含まれるか見ます。
CANDIDATES = FOREACH Data GENERATE
(CASE
WHEN text matches '.*(Hoge|Fuga|Piyo).*' THEN 1
ELSE 0
END) AS flag:int;