2017-04-18 1 views
0

したがって、私が必要とするのは正確にはですが、非常に似ています。主な違いは、必要なすべてのデータが同じコレクションにあることです。 MongoDBの結合に関する私が見た他の答えは、すべてコレクションの間です。異なる種類のドキュメントからのデータを1つのクエリで取得する

私のコレクションには、さまざまな種類のドキュメントがあります。

例のために、これらの二つの検討:それぞれの決定的な特徴は、それらactionある

{ 
    "success" : true, 
    "action" : "logEventGA", 
    "timestamp" : 1490795738759, 
    "terminal" : "3533322585", 
    "device" : { 
     "cordova" : "4.3.0", 
     "model" : "iPhone8,1", 
     "platform" : "iOS", 
     "uuid" : "785ED0AB-996D-4E54-8E0F-404FE076BE4F", 
     "version" : "10.2.1", 
     "manufacturer" : "Apple", 
     "isVirtual" : false, 
     "serial" : "unknown" 
    }, 
    "action_GA" : "login" 
} 

{ 
    "success" : true, 
    "action" : "loginAttempt", 
    "timestamp" : 1483125811453, 
    "terminal" : "3533322585", 
    "id": { 
     "doc": 23324355, 
     "valid": true 
    } 
    "httpCode" : NumberInt("200") 
} 

actionに応じて、オブジェクトには異なる情報があります。

これらの種類のドキュメント(アクション "loginAttempt"と "logEventGA")の情報を取得するためのクエリが必要です。一致するものがあれば、この場合はterminal属性を使用できます。 。

最初の種類のドキュメントでクエリを実行しようとしましたが、forEachよりも他の種類のドキュメントの残りのデータを取得しましたが(順序は関係ありません)、それは辛いです。また、アクションごとに他の基準があります(たとえば、action = loginAttemptの場合、httpCodeは200でなければなりません)。これを一度に行う方法はありますか?

以下は、パフォーマンスが低迷している「参加」の私の試みです。処理するには1行に2秒かかりますが、処理が進むにつれて遅くなり、遅くなるようです。これは使えません。

db.Logging.find({ 
    "timestamp": { $gte: new Date('2017-04-01').getTime() }, 
    "action":"loginAttempt", 
    "httpCode": 200 
}, { 
    terminal: 1, 
    "id.doc": 1, 
    _id: 0 
}).forEach(function(obj) { 
    let eventGA = db.Logging.findOne({"terminal":obj.terminal, "action_GA":"login"},{ _id:0, "device.uuid":1}); 
    console.log(obj.terminal+';'+obj.id.doc+';'+eventGA.device.uuid); 
}); 

期待される成果は、(上記の私のコードまたはCSV形式のように)このようなものになるだろう:

{ 
     "terminal": 3533322585, // from either doc 
     "uuid": "785ED0AB-996D-4E54-8E0F-404FE076BE4F", // from "logEventGA" 
     "doc": 23324355 // from "loginAttempt" 
} 
+0

期待される結果は何ですか?あなたはいつもペアで行動しますか? {$ id: "$ terminal"、first:{"$ group:{$ in:[" logEventGA "、" loginAttempt "]}}}、{$ group:最初の ":" $$ ROOT "}、2番目:{" $ last ":" $$ ROOT "}}})'。上記のクエリは、 'actions'と' terminal'によってグループ化し、両方のドキュメントを投影します。 – Veeram

+0

私は質問を編集し、予想される結果を追加しました。 また、action = loginAttemptの場合はlogEventGAの場合も2番目の基準が必要です。それをどうやってやりますか? –

+0

バージョン3.2以降では '$ cond'式、' $ project'ステージでは3.4バージョンで '$ switch'を使用できます。 – Veeram

答えて

1

あなたは集計クエリの下に試すことができます。これは、2つのペアに対してのみ機能します。

以下のクエリは、データをactionにソートするので、ソートを使用してドキュメントフィールドを投影できます。

db.collection.aggregate(
{$match:{$or:[{ "timestamp": { $gte: new Date('2016-04-01').getTime() }, 
    "action":"loginAttempt", 
    "httpCode": 200},{"action":"logEventGA"}]}}, 
{$sort:{action:1}}, 
{$group:{"_id":"$terminal", "first":{"$first":"$$ROOT"}, "second":{"$last":"$$ROOT"}}}, 
{$project:{terminal:"$_id", device:"$first.device.uuid", doc:"$second.id.doc"}} 
) 
関連する問題