0

次のMySQLコマンドを使用して、ログデータからヒートマップを作成しています。ただし、Mongoデータベースに保存されている新しいデータセットがあり、同じコマンドを実行する必要があります。

 select concat(a.packages '&' b.packages) "Concurrent Packages",
 count(*) "Count"
 from data a
 cross join data b
 where a.packages<b.packages and a.jobID=b.jobID
 group by a.packages, b.packages
 order by a.packages, b.packages;

テーブルaとbは、クエリの前には存在しないことに注意してください。ただし、これらはデータテーブルのpackages列から作成されます。この列には、一致を確認するフィールドとしてjobIDがあります。つまり、2つのパッケージが同じジョブ内にある場合、同時使用数にエントリを追加します。Mongoで同様のクエリを生成するにはどうすればよいですか?

4

2 に答える 2

2

これは異なるドキュメントの「結合」ではありませんこれは1 つのドキュメント内での操作であり、MongoDB で実行できます。

You have a SQL TABLE "data" like this:
  JobID   TEXT,
  package TEXT

これを MongoDB に保存する最良の方法は、パッケージの配列を含む JobID ごとに 1 つのドキュメントを含む「データ」と呼ばれるコレクションです。

{
    _id: <JobID>,
    packages: [
        "packageA",
        "packageB",
        ....
    ]
}

[注: データ テーブルを MongoDB の 1 つのドキュメントとして実装することもできます。これには、それぞれがパッケージの配列を含むジョブの配列が含まれます。16MB のドキュメント サイズ制限に達する可能性があり、ネストされた配列は (まだ) さまざまなクエリで十分にサポートされていないため、これはお勧めしません - データを他の目的にも使用したい場合]

さて、このような結果を得るにはどうすればよいでしょうか?

{ pair: [ "packageA", "packageB" ], count: 20 },
{ pair: [ "packageA", "packageC" ], count: 11 },
...

MongoDB には 2 つの配列の組み込みの「クロス結合」がないため、mapReduce() のマップ関数でプログラムして、パッケージの各ペアをキーとして発行する必要があります。

mapf = function () {
    that = this;
    this.packages.forEach( function( p1 ) {
        that.packages.forEach( function( p2 ) {
            if ( p1 < p2 ) {
                key = { "pair": [ p1, p2 ] };
                emit( key, 1 );
            };
        });
    });
};

[注: パッケージ配列がソートされている場合、これは最適化される可能性があります]

reduce 関数は、各キーのカウンターを合計するだけです。

reducef = function( key, values ) {
    count = 0;
    values.forEach( function( value ) { count += value } );
    return count;
};

したがって、このサンプル コレクションの場合:

> db.data.find()
{ "_id" : "Job01", "packages" : [ "pA", "pB", "pC" ] }
{ "_id" : "Job02", "packages" : [ "pA", "pC" ] }
{ "_id" : "Job03", "packages" : [ "pA", "pB", "pD", "pE" ] }

we get the following result:

> db.data.mapReduce(
...     mapf,
...     reducef,
...     { out: 'pairs' }
... );
{
    "result" : "pairs",
    "timeMillis" : 443,
    "counts" : {
        "input" : 3,
        "emit" : 10,
        "reduce" : 2,
        "output" : 8
    },
    "ok" : 1,
}
> db.pairs.find()
{ "_id" : { "pair" : [ "pA", "pB" ] }, "value" : 2 }
{ "_id" : { "pair" : [ "pA", "pC" ] }, "value" : 2 }
{ "_id" : { "pair" : [ "pA", "pD" ] }, "value" : 1 }
{ "_id" : { "pair" : [ "pA", "pE" ] }, "value" : 1 }
{ "_id" : { "pair" : [ "pB", "pC" ] }, "value" : 1 }
{ "_id" : { "pair" : [ "pB", "pD" ] }, "value" : 1 }
{ "_id" : { "pair" : [ "pB", "pE" ] }, "value" : 1 }
{ "_id" : { "pair" : [ "pD", "pE" ] }, "value" : 1 }

mapReduce の詳細については、http://docs.mongodb.org/manual/reference/method/db.collection.mapReduce/および http://docs.mongodb.org/manual/applications/map-reduce/参照してください。

于 2013-04-02T01:52:34.190 に答える
1

できません。Mongo は結合を行いません。SQL から Mongo への切り替えは、クエリの移行よりもはるかに複雑です。

通常、すべての関連情報を同じレコードに含めます (情報を正規化して結合で選択するのではなく)。非正規化!

于 2013-03-08T02:15:47.817 に答える