0

私は Apache Pig の新しいユーザーで、解決すべき問題があります。

apache pig でちょっとした検索エンジンを作ろうとしています。アイデアは単純です。複数のドキュメントを連結したファイルがあります (1 行に 1 つのドキュメント)。3 つのドキュメントの例を次に示します。

1,word1 word4 word2 word1
2,word2 word6 word1 word5 word3
3,word1 word3 word4 word5

次に、次のコード行を使用して、ドキュメントごとに Bag of words を作成します。

docs = LOAD '$documents' USING PigStorage(',') AS (id:int, line:chararray);
B = FOREACH docs GENERATE line;
C = FOREACH B GENERATE TOKENIZE(line) as gu;

次に、バッグの重複するエントリを削除します。

filtered = FOREACH C {
    uniq = DISTINCT gu;
    GENERATE uniq;
}

このコードの結果は次のとおりです。

DUMP filtered;

({(word1), (word4),  (word2)})
({(word2), (word6),  (word1), (word5), (word3)})
({(word1), (word3),  (word4), (word5)})

そのため、私が望んでいたように、ドキュメントごとに単語のバッグがあります。

ここで、ユーザー クエリをファイルとして考えてみましょう。

word2 word7 word5

クエリを一連の単語に変換します。

query = LOAD '$query' AS (line_query:chararray);
bag_query = FOREACH query GENERATE TOKENIZE(line_query) AS quer;

DUMP bag_query;

結果は次のとおりです。

({(word2), (word7), (word5)})

さて、ここに私の問題があります。クエリと各ドキュメントの間の一致数を取得したいと思います。この例では、次の出力が必要です。

1
2
1

バッグ間に JOIN を作成しようとしましたが、うまくいきませんでした。

私を手伝ってくれますか ?

ありがとうございました。

4

3 に答える 3

1

UDF を使用しなくてもよい場合は、バッグをピボットしてすべて SQL スタイルにすることで実行できます。

docs = LOAD '/input/search.dat' USING PigStorage(',') AS (id:int, line:chararray);
C = FOREACH docs GENERATE id, TOKENIZE(line) as gu;
pivoted = FOREACH C {
    uniq = DISTINCT gu;
        GENERATE id, FLATTEN(uniq) as word;
};
filtered = FILTER pivoted BY word MATCHES '(word2|word7|word5)';
--dump filtered;
count_id_matched = FOREACH (GROUP filtered BY id) GENERATE group as id, COUNT(filtered) as count;

dump count_id_matched;

count_word_matched_in_docs = FOREACH (GROUP filtered BY word) GENERATE group as word, COUNT(filtered) as count;

dump count_word_matched_in_docs;
于 2013-05-22T17:14:18.850 に答える
0

SNeumann が指摘したように、例として DataFu の SetIntersect を使用できます。

これらのドキュメントを考慮して、例を構築します。

1,word1 word4 word2 word1
2,word2 word6 word1 word5 word3 word7
3,word1 word3 word4 word5

そして、次のクエリが与えられます:

word2 word7 word5

次に、このコードはあなたが望むものを提供します:

define SetIntersect datafu.pig.sets.SetIntersect();

docs = LOAD 'docs' USING PigStorage(',') AS (id:int, line:chararray);
B = FOREACH docs GENERATE id, line;
C = FOREACH B GENERATE id, TOKENIZE(line) as gu;

filtered = FOREACH C {
  uniq = DISTINCT gu;
  GENERATE id, uniq;
}

query = LOAD 'query' AS (line_query:chararray);
bag_query = FOREACH query GENERATE TOKENIZE(line_query) AS query;
-- sort the bag of tokens, since SetIntersect requires it
bag_query = FOREACH bag_query {
  query_sorted = ORDER query BY token;
  GENERATE query_sorted;
}

result = FOREACH filtered {
  -- sort the tokens, since SetIntersect requires it
  tokens_sorted = ORDER uniq BY token;
  GENERATE id, 
           SIZE(SetIntersect(tokens_sorted,bag_query.query_sorted)) as cnt;
}

DUMP result;

結果の値:

(1,1)
(2,3)
(3,1)

ここにある SetIntersect の DataFu 単体テストに貼り付けることができる完全に機能する例を次に示します。

/**
register $JAR_PATH

define SetIntersect datafu.pig.sets.SetIntersect();

docs = LOAD 'docs' USING PigStorage(',') AS (id:int, line:chararray);
B = FOREACH docs GENERATE id, line;
C = FOREACH B GENERATE id, TOKENIZE(line) as gu;

filtered = FOREACH C {
  uniq = DISTINCT gu;
  GENERATE id, uniq;
}

query = LOAD 'query' AS (line_query:chararray);
bag_query = FOREACH query GENERATE TOKENIZE(line_query) AS query;
-- sort the bag of tokens, since SetIntersect requires it
bag_query = FOREACH bag_query {
  query_sorted = ORDER query BY token;
  GENERATE query_sorted;
}

result = FOREACH filtered {
  -- sort the tokens, since SetIntersect requires it
  tokens_sorted = ORDER uniq BY token;
  GENERATE id, 
           SIZE(SetIntersect(tokens_sorted,bag_query.query_sorted)) as cnt;
}

DUMP result;

 */
@Multiline
private String setIntersectTestExample;

@Test
public void setIntersectTestExample() throws Exception
{    
  PigTest test = createPigTestFromString(setIntersectTestExample);    

  writeLinesToFile("docs", 
                   "1,word1 word4 word2 word1",
                   "2,word2 word6 word1 word5 word3 word7",
                   "3,word1 word3 word4 word5");

  writeLinesToFile("query", 
                   "word2 word7 word5");

  test.runScript();

  super.getLinesForAlias(test, "filtered");
  super.getLinesForAlias(test, "query");
  super.getLinesForAlias(test, "result");
}

他にも同様の使用例があれば、ぜひ聞かせてください :) 私たちは常に、より有用な UDF を DataFu に提供できるよう努めています。

于 2013-12-03T18:03:01.747 に答える