Mongodb:根据条件填充
Mongodb: Populate based on condition
我有一些 collection,我正在尝试将日志 object 转换为它的详细信息(使用 populate
)。
Companies
(公司及其用户):
[
{
_id: "comp123",
companyId: "compName123",
users: [
{ user: "user111", status: "active"},
{ user: "user222", status: "active"},
]
},
{
_id: "comp456",
name: "compName456",
users: [
{ user: "user333", status: "active"}
]
},
{
_id: "comp789",
name: "compName789",
users: [
{ user: "user444", status: "inactive"}
]
},
]
Users:
[
{_id: "user111", firstName: "userName111"},
{_id: "user222", firstName: "userName222"},
{_id: "user333", firstName: "userName333"},
{_id: "user444", firstName: "userName444"},
]
我正在尝试将 log
collection 转换为数据。
examples:
对于 log
的第一个 object:
{
companyId: "comp123",
actionDetails: [
entities: [
{ id: "user111", entityType: "User"}
]
]
},
我想要 return:
{
companyId: {_id: "comp123", name: "compName123"}, // taken from companies
userId: { _id: "user111", firstName: "userName111"}, // taken from users
// Does company=comp123 that has a user with user=user111 and status=active exist?
isUserActiveInCompany: true
}
日志的另一个例子:
{
companyId: "comp456",
actionDetails: [
entities: [
{ id: "user444", entityType: "User"}
]
]
}
输出为:
{
companyId: {_id: "comp456", name: "compName456"}, // taken from companies
userId: { _id: "user444", firstName: "userName444"}, // taken from users
isUserActiveInCompany: false // Does company=comp456 that has a user with user=user444 and status=active exist?
}
日志的最后一个重要示例:
{
companyId: "comp789",
actionDetails: [
entities: [
{ id: "attr333", entityType: "Attribute"}
]
]
}
输出:
{
companyId: {_id: "comp789", name: "compName789"}, // taken from companies
userId: {}, // taken from users (entityType is Attribute so we ignore it)
isUserActiveInCompany: null // entityType is Attribute so we ignore it
}
如果有comp789 和user444 的日志,isUserActiveInCompany 应该是false(因为用户在他的公司不活跃)。
目前,我是:
populate([
{
path: "actionDetails.entities.id",
select: "id firstName",
},
{
path: "companyId",
select: "name",
},
]
感谢任何帮助!
将以下聚合管道代码转换为 Mongoose 等价物以获得您想要的输出。
db.log.aggregate([
{
'$match': {
// <-- I highly recommend that you use a `$match` condition since there are 2 lookup operators in the aggregation which will significantly increase execution time.
}
},
{
'$lookup': {
'from': 'Companies',
'let': {'cId': '$companyId'},
'pipeline': [
{
'$match': {
'$expr': {
'$eq': ['$_id', '$$cId']
}
}
},
{
"$project": {
'company': {
"_id": "$_id",
"companyName": "$companyId"
},
'users': {
"$filter": {
'input': "$users",
'as': "usr",
'cond': {
"$eq": ["$$usr.status", "active"],
},
},
},
}
},
],
'as': 'companyDetails'
}
},
{
'$unwind': {
'path': "$actionDetails",
}
},
{
'$unwind': {
'path': "$actionDetails.entities",
}
},
{
'$lookup': {
'from': 'Users',
'let': {"uId": "$actionDetails.entities.id"},
'pipeline': [
{
"$match": {
"$expr": {
"$eq": ["$_id", "$$uId"],
},
},
},
{
"$project": {
"firstName": 1,
},
},
],
'as': "userDetails",
}
},
{
'$project': {
"companyId": {"$arrayElemAt": ["$companyDetails.company", 0]},
"userId": {
"_id": "$actionDetails.entities.id",
"firstName": {"$arrayElemAt": ["$userDetails.firstName", 0]},
},
"isUserActiveInCompany": {
"$switch": {
"branches": [
{
'case': {
"$ne": ["$actionDetails.entities.entityType", "User"]
},
'then': null,
},
{
'case': {
"$in": [
"$actionDetails.entities.id",
{
"$map": {
'input': {"$arrayElemAt": ["$companyDetails.users", 0]},
'as': "elem",
'in': "$$elem.user"
}
}
]
},
'then': true,
},
],
'default': false,
}
}
}
}
], {
'allowDiskUse': true,
});
如果你想要每个阶段的完整解释和逻辑,请告诉我。
我有一些 collection,我正在尝试将日志 object 转换为它的详细信息(使用 populate
)。
Companies
(公司及其用户):
[
{
_id: "comp123",
companyId: "compName123",
users: [
{ user: "user111", status: "active"},
{ user: "user222", status: "active"},
]
},
{
_id: "comp456",
name: "compName456",
users: [
{ user: "user333", status: "active"}
]
},
{
_id: "comp789",
name: "compName789",
users: [
{ user: "user444", status: "inactive"}
]
},
]
Users:
[
{_id: "user111", firstName: "userName111"},
{_id: "user222", firstName: "userName222"},
{_id: "user333", firstName: "userName333"},
{_id: "user444", firstName: "userName444"},
]
我正在尝试将 log
collection 转换为数据。
examples:
对于 log
的第一个 object:
{
companyId: "comp123",
actionDetails: [
entities: [
{ id: "user111", entityType: "User"}
]
]
},
我想要 return:
{
companyId: {_id: "comp123", name: "compName123"}, // taken from companies
userId: { _id: "user111", firstName: "userName111"}, // taken from users
// Does company=comp123 that has a user with user=user111 and status=active exist?
isUserActiveInCompany: true
}
日志的另一个例子:
{
companyId: "comp456",
actionDetails: [
entities: [
{ id: "user444", entityType: "User"}
]
]
}
输出为:
{
companyId: {_id: "comp456", name: "compName456"}, // taken from companies
userId: { _id: "user444", firstName: "userName444"}, // taken from users
isUserActiveInCompany: false // Does company=comp456 that has a user with user=user444 and status=active exist?
}
日志的最后一个重要示例:
{
companyId: "comp789",
actionDetails: [
entities: [
{ id: "attr333", entityType: "Attribute"}
]
]
}
输出:
{
companyId: {_id: "comp789", name: "compName789"}, // taken from companies
userId: {}, // taken from users (entityType is Attribute so we ignore it)
isUserActiveInCompany: null // entityType is Attribute so we ignore it
}
如果有comp789 和user444 的日志,isUserActiveInCompany 应该是false(因为用户在他的公司不活跃)。
目前,我是:
populate([
{
path: "actionDetails.entities.id",
select: "id firstName",
},
{
path: "companyId",
select: "name",
},
]
感谢任何帮助!
将以下聚合管道代码转换为 Mongoose 等价物以获得您想要的输出。
db.log.aggregate([
{
'$match': {
// <-- I highly recommend that you use a `$match` condition since there are 2 lookup operators in the aggregation which will significantly increase execution time.
}
},
{
'$lookup': {
'from': 'Companies',
'let': {'cId': '$companyId'},
'pipeline': [
{
'$match': {
'$expr': {
'$eq': ['$_id', '$$cId']
}
}
},
{
"$project": {
'company': {
"_id": "$_id",
"companyName": "$companyId"
},
'users': {
"$filter": {
'input': "$users",
'as': "usr",
'cond': {
"$eq": ["$$usr.status", "active"],
},
},
},
}
},
],
'as': 'companyDetails'
}
},
{
'$unwind': {
'path': "$actionDetails",
}
},
{
'$unwind': {
'path': "$actionDetails.entities",
}
},
{
'$lookup': {
'from': 'Users',
'let': {"uId": "$actionDetails.entities.id"},
'pipeline': [
{
"$match": {
"$expr": {
"$eq": ["$_id", "$$uId"],
},
},
},
{
"$project": {
"firstName": 1,
},
},
],
'as': "userDetails",
}
},
{
'$project': {
"companyId": {"$arrayElemAt": ["$companyDetails.company", 0]},
"userId": {
"_id": "$actionDetails.entities.id",
"firstName": {"$arrayElemAt": ["$userDetails.firstName", 0]},
},
"isUserActiveInCompany": {
"$switch": {
"branches": [
{
'case': {
"$ne": ["$actionDetails.entities.entityType", "User"]
},
'then': null,
},
{
'case': {
"$in": [
"$actionDetails.entities.id",
{
"$map": {
'input': {"$arrayElemAt": ["$companyDetails.users", 0]},
'as': "elem",
'in': "$$elem.user"
}
}
]
},
'then': true,
},
],
'default': false,
}
}
}
}
], {
'allowDiskUse': true,
});
如果你想要每个阶段的完整解释和逻辑,请告诉我。