2017-04-18 59 views
0

所以,我需要的不是恰好是的一個連接,而是非常相似的東西。主要區別是我需要的所有數據都在同一個集合中。我見過的其他與MongoDB中的連接有關的答案都在集合之間。從一個查詢中獲取不同類型文檔的數據

在我的收藏中,我有不同類型的文檔。

例如起見,考慮這兩個:

{ 
    "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。根據action,對象將具有不同的信息。因此,我需要一個查詢來獲取來自這兩種文檔(動作「loginAttempt」和「logEventGA」)的信息,並且匹配(join?)它們 - 在這種情況下,我們可以使用terminal屬性。

我試着在第一種文檔上運行查詢,而不是forEach來獲取其他類型文檔的剩餘數據(順序無關緊要),但是速度很慢。此外,每個操作還有其他標準(例如,當action = loginAttempt時,httpCode必須是200)。有沒有辦法一次完成這一切?

以下是我對「表現不佳」的「加入」的嘗試。每行處理需要兩秒鐘的時間,而且它似乎越來越慢。不能使用這個。

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

您的預期結果是什麼?你總是有行動成對嗎?類似於'db.collection.aggregate({$ match:{action:{$ in:[「logEventGA」,「loginAttempt」]}},{$ group:{_ id:「$ terminal」,first:{「$第一個「:」$$ ROOT「},第二個:{」$ last「:」$$ ROOT「}}})'。上面的查詢通過'terminal'匹配'actions'和group並且投影這兩個文檔。 – Veeram

+0

我編輯了問題並添加了預期結果。 另外,當action = loginAttempt時,我需要第二個條件,還有一個用於logEventGA。我會怎麼做呢? –

+0

您可以在3.2版本及以下版本中使用'$ cond'表達式,在'$ project'階段使用3.4版本的'$ switch'。 – Veeram

回答

1

你可以試試下面的聚集查詢。這隻適用於一對兩個。

以下查詢對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"}} 
) 
相關問題