从一个查询中获取不同类型文档的数据

从一个查询中获取不同类型文档的数据

问题描述:

所以,我需要的不是恰好是的一个连接,而是非常相似的东西。主要区别是我需要的所有数据都在同一个集合中。我见过的其他与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

你可以试试下面的聚集查询。这只适用于一对两个。

以下查询对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"}} 
)