从一个查询中获取不同类型文档的数据
问题描述:
所以,我需要的不是恰好是的一个连接,而是非常相似的东西。主要区别是我需要的所有数据都在同一个集合中。我见过的其他与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"
}
答
你可以试试下面的聚集查询。这只适用于一对两个。
以下查询对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"}}
)
您的预期结果是什么?你总是有行动成对吗?类似于'db.collection.aggregate({$ match:{action:{$ in:[“logEventGA”,“loginAttempt”]}},{$ group:{_ id:“$ terminal”,first:{“$第一个“:”$$ ROOT“},第二个:{”$ last“:”$$ ROOT“}}})'。上面的查询通过'terminal'匹配'actions'和group并且投影这两个文档。 – Veeram
我编辑了问题并添加了预期结果。 另外,当action = loginAttempt时,我需要第二个条件,还有一个用于logEventGA。我会怎么做呢? –
您可以在3.2版本及以下版本中使用'$ cond'表达式,在'$ project'阶段使用3.4版本的'$ switch'。 – Veeram