好吧,如果我理解得很好,这将通过使用$lookup 和$unwind(可选)阶段来实现。
由于查找已为我们“合并/加入”集合,因此您可以通过$match 阶段查询任何条件,并通过$group 阶段aggregation pipeline 进行分组:
我们考虑以下集合:
var sessionsLog = [
{
'userId': "132",
'deviceType': "ios",
'startDate': ISODate('2018-02-23'),
'endDate': ISODate('2018-02-28')
},
{
'userId': "789",
'deviceType': "android",
'startDate': ISODate('2018-02-15'),
'endDate': ISODate('2018-02-19')
},
{
'userId': "225",
'deviceType': "ios",
'startDate': ISODate('2018-03-01'),
'endDate': ISODate('2018-03-17')
}
];
var actionsLog = [
{
'userId': '225',
'deviceType': 'ios',
'createdAt': ISODate('2018-03-03'),
'action': 'X'
},
{
'userId': '789',
'deviceType': 'android',
'createdAt': ISODate('2018-02-16'),
'action': 'Y'
},
{
'userId': '789',
'deviceType': 'android',
'createdAt': ISODate('2018-02-16'),
'action': 'Z'
}
];
db.actionLogs.insert(actionsLog); //via mongo shell...
db.sessionLogs.insert(sessionsLog); //via mongo sheell...
第 1 步:加入集合
这是$lookup 运算符派上用场的时候。在这里,我们将加入 userId 字段的集合,但您想要什么取决于您按字段“连接”集合!
db.sessionLogs.aggregate([
{
$lookup: {
from: 'actionLogs',
foreignField: 'userId',
localField: 'userId',
as: 'action_log'
}
}
])
第 2 步:过滤文档
我需要获取具有特定操作日志的会话日志列表。
(以及其他过滤器,如日期、用户等...)
一旦我们加入了集合,就应该很容易使用 $match 运算符按特定条件获取/过滤文档。
但在此之前,我认为在$match 舞台之前添加$unwind 舞台确实会使工作变得更容易(但根本不需要),所以它会是:
db.sessionLogs.aggregate([
{
$lookup: {
from: 'actionLogs',
foreignField: 'userId',
localField: 'userId',
as: 'action_log'
}
},
{
$unwind: '$action_logs'
}
])
然后它返回:
{
"_id": ObjectId("5ab463233a856b4829f5e75d"),
"userId": "789",
"deviceType": "android",
"startDate": ISODate("2018-02-15T00:00:00Z"),
"endDate": ISODate("2018-02-19T00:00:00Z"),
"action_log": {
"_id": ObjectId("5ab463363a856b4829f5e760"),
"userId": "789",
"deviceType": "android",
"createdAt": ISODate("2018-02-16T00:00:00Z"),
"action": "Y"
}
},
{
"_id": ObjectId("5ab463233a856b4829f5e75d"),
"userId": "789",
"deviceType": "android",
"startDate": ISODate("2018-02-15T00:00:00Z"),
"endDate": ISODate("2018-02-19T00:00:00Z"),
"action_log": {
"_id": ObjectId("5ab463363a856b4829f5e761"),
"userId": "789",
"deviceType": "android",
"createdAt": ISODate("2018-02-16T00:00:00Z"),
"action": "Z"
}
},
{
"_id": ObjectId("5ab463233a856b4829f5e75e"),
"userId": "225",
"deviceType": "ios",
"startDate": ISODate("2018-03-01T00:00:00Z"),
"endDate": ISODate("2018-03-17T00:00:00Z"),
"action_log": {
"_id": ObjectId("5ab463363a856b4829f5e75f"),
"userId": "225",
"deviceType": "ios",
"createdAt": ISODate("2018-03-03T00:00:00Z"),
"action": "X"
}
}
现在我们可以像这样过滤文档(action 等于 X):
db.sessionLogs.aggregate([
{
$lookup: {
from: 'actionLogs',
foreignField: 'userId',
localField: 'userId',
as: 'action_log'
}
},
{
$unwind: '$action_log'
},
{
$match: {'action_log.action': 'X' }
}
])
同样,通过为聚合管道添加$group 阶段进行分组应该很容易!
旁注: