我有一个像这样的employeeResponses
文档,并且我试图针对[
{
...
eventDate: 2019-10-08T03:30:15.000+00:00,
employeeResponses: [
{
_id:"5d978d372f263f41cc624727",
response: "Available to work.",
notes: ""
},
...etc
];
}
];
数组进行查询,以收集单个雇员的所有响应(可能存在或可能不存在):
const eventResponses = await Event.aggregate([
{
// find all events for a selected month
$match: {
eventDate: {
$gte: startOfMonth,
$lte: endOfMonth,
},
},
},
{
// unwind the employeeResponses array
$unwind: {
path: "$employeeResponses",
preserveNullAndEmptyArrays: true,
},
},
{
$group: {
_id: null,
responses: {
$push: {
// if a response id matches the employee's id, then
// include their response; otherwise, it's a "No response."
$cond: [
{ $eq: ["$employeeResponses._id", existingMember._id] },
"$employeeResponses.response",
"No response.",
],
},
},
},
},
{ $project: { _id: 0, responses: 1 } },
]);
我当前的猫鼬聚合是:
employeeResponses
您会毫无疑问地注意到,上面的查询在一个以上的员工记录了一个响应之后将不起作用,因为它将每个单独的响应都视为T / F条件,而不是所有响应$match
数组中的strong>作为单个T / F条件。
结果,我删除了最初const responses = eventResponses.reduce((acc, { employeeResponses }) => {
const foundResponse = employeeResponses.find(response => response._id.equals(existingMember._id));
return [...acc, foundResponse ? foundResponse.response : "No response."];
}, []);
之后的所有后续查询,并进行了手动减少:
$reduce
我想知道是否有可能获得与上述相同的减少结果,但是也许使用mongo的employeeResponses
函数?还是重构上面的聚合查询,将Event
内的所有响应都视为一个T / F条件?
此汇总的最终目标是从当月发现的每个["I want to work.", "Available to work.", "Not available to work.", "No response.", "No response." ...etc]
中提取每个先前记录的员工的答复和/或缺少答复,并将他们的答复放入一个单独的数组中:
{{1}}
答案 0 :(得分:2)
您可以将$filter与$map结合使用来重塑数据并按_id
进行过滤。然后,如果数组为空,则可以继续使用$push和$ifNull来提供默认值:
db.collection.aggregate([
{
$addFields: {
employeeResponses: {
$map: {
input: {
$filter: {
input: "$employeeResponses",
cond: {
$eq: [ "$$this._id", "5d978d372f263f41cc624727"]
}
}
},
in: "$$this.response"
}
}
}
},
{
$group: {
_id: null,
responses: { $push: { $ifNull: [ { $arrayElemAt: [ "$employeeResponses", 0 ] }, "No response" ] } }
}
}
])