列出一个集合中的文档并计算它们在另一个集合中的出现次数
List documents from a collection and count their occurrence in another collection
我是 MongoDB 聚合的新手,我正在摸索如何用 Mongo:
做类似的事情
示例SQL查询(如果这是一个关系数据库):
select id, name, (select max(createdAt) from events where user_id=u.id)
from users u
或者..
select users.id, users.name, max(events.created_at)
from users inner join events on users.id=events.user_id
group by users.id, users.name
最后的结果是一样的。我想列出所有用户,以及他们最近活动的最大日期。
如何在 Mongo 上完成此操作?
假设我有一个具有相同字段的用户和事件集合。
我想我应该从 $lookup 开始,它会把事件和用户文档放在一起。
[{
$match: {
accountId: '629a251af534a3600aa1a150'
}
}, {
$lookup: {
from: 'productevents',
localField: 'id',
foreignField: 'userId',
as: 'userEvents'
}
}, {}]
只是不确定下一步要做什么才能计算剩余事件集合中的 get max(created_at)。
示例数据:
用户:
{
"id": "1",
"accountId": "629a251af534a3600aa1a150",
"name": "Some User",
"createdAt": {
"$date": {
"$numberLong": "1654269244479"
}
},
"properties": {
"age": "39"
},
"__v": 0
}
产品事件:
{
"name": "login",
"accountId": "629a251af534a3600aa1a150",
"userId": "1",
"groupId": "1",
"properties": {
"client": "mobile"
},
"createdAt": {
"$date": {
"$numberLong": "1654269289432"
}
},
"__v": 0
}
找到了一种方法(尽管不确定它是否是最佳方法)。
[
{
'$lookup': {
'from': 'productevents',
'localField': 'id',
'foreignField': 'userId',
'as': 'events'
}
}, {
'$unwind': {
'path': '$events',
'preserveNullAndEmptyArrays': true
}
}, {
'$group': {
'_id': {
'id': '$id',
'name': '$name',
'_id': '$_id',
'createdAt': '$createdAt',
'properties': '$properties'
},
'lastActivity': {
'$max': '$events.createdAt'
}
}
}, {
'$project': {
'_id': '$_id._id',
'id': '$_id.id',
'createdAt': '$_id.createdAt',
'properties': '$_id.properties',
'lastActivity': 1
}
}
]
您可以使用 $lookup pipeline
进行优化,方法是仅从 productevents
集合中获取您需要的内容:
db.users.aggregate([
{
$lookup: {
from: "productevents",
let: {id: "$id"},
pipeline: [
{$match: {$expr: {$eq: ["$userId", "$$id"]}}}
{$sort: {createdAt: -1}},
{$limit: 1},
{$project: {createdAt: 1, _id: 0}}
],
as: "lastActivity"
}
},
{
$set: {lastActivity: {$arrayElemAt: ["$lastActivity", 0]}}
},
{
$project: {
id: 1,
createdAt: 1,
properties: 1,
lastActivity: "$lastActivity.createdAt"
}
}
])
编辑:
如果您需要计算每个用户的事件数,您也可以在 $lookup
管道内进行:
db.users.aggregate([
{
$lookup: {
from: "productevents",
let: {id: "$id"},
pipeline: [
{$match: {$expr: {$eq: ["$userId", "$$id"]}}}
{$group: {_id: 0, count: {$sum: 1}, createdAt: {$max: "$createdAt"}}}
],
as: "lastActivity"
}
},
{
$set: {lastActivity: {$arrayElemAt: ["$lastActivity", 0]}}
},
{
$project: {
id: 1,
createdAt: 1,
properties: 1,
lastActivity: "$lastActivity.createdAt",
activityCount: "$lastActivity.count"
}
}
])
我是 MongoDB 聚合的新手,我正在摸索如何用 Mongo:
做类似的事情示例SQL查询(如果这是一个关系数据库):
select id, name, (select max(createdAt) from events where user_id=u.id)
from users u
或者..
select users.id, users.name, max(events.created_at)
from users inner join events on users.id=events.user_id
group by users.id, users.name
最后的结果是一样的。我想列出所有用户,以及他们最近活动的最大日期。
如何在 Mongo 上完成此操作?
假设我有一个具有相同字段的用户和事件集合。
我想我应该从 $lookup 开始,它会把事件和用户文档放在一起。
[{
$match: {
accountId: '629a251af534a3600aa1a150'
}
}, {
$lookup: {
from: 'productevents',
localField: 'id',
foreignField: 'userId',
as: 'userEvents'
}
}, {}]
只是不确定下一步要做什么才能计算剩余事件集合中的 get max(created_at)。
示例数据:
用户:
{
"id": "1",
"accountId": "629a251af534a3600aa1a150",
"name": "Some User",
"createdAt": {
"$date": {
"$numberLong": "1654269244479"
}
},
"properties": {
"age": "39"
},
"__v": 0
}
产品事件:
{
"name": "login",
"accountId": "629a251af534a3600aa1a150",
"userId": "1",
"groupId": "1",
"properties": {
"client": "mobile"
},
"createdAt": {
"$date": {
"$numberLong": "1654269289432"
}
},
"__v": 0
}
找到了一种方法(尽管不确定它是否是最佳方法)。
[
{
'$lookup': {
'from': 'productevents',
'localField': 'id',
'foreignField': 'userId',
'as': 'events'
}
}, {
'$unwind': {
'path': '$events',
'preserveNullAndEmptyArrays': true
}
}, {
'$group': {
'_id': {
'id': '$id',
'name': '$name',
'_id': '$_id',
'createdAt': '$createdAt',
'properties': '$properties'
},
'lastActivity': {
'$max': '$events.createdAt'
}
}
}, {
'$project': {
'_id': '$_id._id',
'id': '$_id.id',
'createdAt': '$_id.createdAt',
'properties': '$_id.properties',
'lastActivity': 1
}
}
]
您可以使用 $lookup pipeline
进行优化,方法是仅从 productevents
集合中获取您需要的内容:
db.users.aggregate([
{
$lookup: {
from: "productevents",
let: {id: "$id"},
pipeline: [
{$match: {$expr: {$eq: ["$userId", "$$id"]}}}
{$sort: {createdAt: -1}},
{$limit: 1},
{$project: {createdAt: 1, _id: 0}}
],
as: "lastActivity"
}
},
{
$set: {lastActivity: {$arrayElemAt: ["$lastActivity", 0]}}
},
{
$project: {
id: 1,
createdAt: 1,
properties: 1,
lastActivity: "$lastActivity.createdAt"
}
}
])
编辑:
如果您需要计算每个用户的事件数,您也可以在 $lookup
管道内进行:
db.users.aggregate([
{
$lookup: {
from: "productevents",
let: {id: "$id"},
pipeline: [
{$match: {$expr: {$eq: ["$userId", "$$id"]}}}
{$group: {_id: 0, count: {$sum: 1}, createdAt: {$max: "$createdAt"}}}
],
as: "lastActivity"
}
},
{
$set: {lastActivity: {$arrayElemAt: ["$lastActivity", 0]}}
},
{
$project: {
id: 1,
createdAt: 1,
properties: 1,
lastActivity: "$lastActivity.createdAt",
activityCount: "$lastActivity.count"
}
}
])