node.js 如何在同一个语句中使用填充和聚合?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16680015/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to use populate and aggregate in same statement?
提问by Nour Sammour
This is my appointment collection:
这是我的约会合集:
{ _id: ObjectId("518ee0bc9be1909012000002"), date: ISODate("2013-05-13T22:00:00Z"), patient:ObjectId("518ee0bc9be1909012000002") }
{ _id: ObjectId("518ee0bc9be1909012000002"), date: ISODate("2013-05-13T22:00:00Z"), patient:ObjectId("518ee0bc9be1909012000002") }
{ _id: ObjectId("518ee0bc9be1909012000002"), date: ISODate("2013-05-13T22:00:00Z"), patient:ObjectId("518ee0bc9be1909012000002") }
I used aggregate to get the following result
我使用聚合得到以下结果
{date: ISODate("2013-05-13T22:00:00Z"),
patients:[ObjectId("518ee0bc9be1909012000002"),ObjectId("518ee0bc9be1909012000002"),ObjectId("518ee0bc9be1909012000002")] }
like this:
像这样:
Appointments.aggregate([
{$group: {_id: '$date', patients: {$push: '$patient'}}},
{$project: {date: '$_id', patients: 1, _id: 0}}
], ...)
How can I populate the patient document
I trued this but it doesn't work ... Appointments.find({}).populate("patient").aggregate....
我怎样才能填充我确认过的患者文件,但它不起作用Appointments.find({}).populate("patient").aggregate......
In other words, can i use populate and aggregate at the same statement
换句话说,我可以在同一个语句中使用填充和聚合吗?
any help please
任何帮助请
回答by ruffrey
With the latest version of mongoose (mongoose >= 3.6), you canbut it requires a second query, and using populate differently. After your aggregation, do this:
使用最新版本的猫鼬(猫鼬 >= 3.6),您可以,但它需要第二次查询,并且以不同的方式使用填充。聚合后,执行以下操作:
Patients.populate(result, {path: "patient"}, callback);
See more at the Mongoose APIand the Mongoose docs.
在Mongoose API和Mongoose 文档中查看更多信息。
回答by Lotus
You can use $lookup which is similar to populate.
您可以使用类似于填充的 $lookup。
In an unrelated example, I use $match to query for records and $lookup to populate a foreign model as a sub-property of these records:
在一个不相关的示例中,我使用 $match 查询记录,使用 $lookup 填充外部模型作为这些记录的子属性:
Invite.aggregate(
{ $match: {interview: req.params.interview}},
{ $lookup: {from: 'users', localField: 'email', foreignField: 'email', as: 'user'} }
).exec( function (err, invites) {
if (err) {
next(err);
}
res.json(invites);
}
);
回答by Mohammed Abo-zaid
You can do it in one query like this:
您可以在这样的一个查询中执行此操作:
Appointments.aggregate([{
$group: {
_id: '$date',
patients: {
$push: '$patient'
}
}
},
{
$project: {
date: '$_id',
patients: 1,
_id: 0
}
},
{
$lookup: {
from: "patients",
localField: "patient",
foreignField: "_id",
as: "patient_doc"
}
}
])
populate basically uses $lookup under the hood. in this case no need for a second query. for more details check MongoDB aggregation lookup
populate 基本上在幕后使用 $lookup 。在这种情况下不需要第二次查询。有关更多详细信息,请检查MongoDB 聚合查找
回答by Libu Mathew
Perform a Join with $lookup
使用 $lookup 执行连接
A collection orders contains the following documents:
一个托收订单包含以下文件:
{ "_id" : 1, "item" : "abc", "price" : 12, "quantity" : 2 }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1 }
{ "_id" : 3 }
Another collection inventory contains the following documents:
另一个馆藏清单包含以下文件:
{ "_id" : 1, "sku" : "abc", description: "product 1", "instock" : 120 }
{ "_id" : 2, "sku" : "def", description: "product 2", "instock" : 80 }
{ "_id" : 3, "sku" : "ijk", description: "product 3", "instock" : 60 }
{ "_id" : 4, "sku" : "jkl", description: "product 4", "instock" : 70 }
{ "_id" : 5, "sku": null, description: "Incomplete" }
{ "_id" : 6 }
The following aggregation operation on the orders collection joins the documents from orders with the documents from the inventory collection using the fields item from the orders collection and the sku field from the inventory collection:
以下对 orders 集合的聚合操作使用来自 orders 集合的字段 item 和来自库存集合的 sku 字段将来自订单的文档与来自库存集合的文档连接起来:
db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "inventory_docs"
}
}
])
The operation returns the following documents:
该操作返回以下文档:
{
"_id" : 1,
"item" : "abc",
"price" : 12,
"quantity" : 2,
"inventory_docs" : [
{ "_id" : 1, "sku" : "abc", description: "product 1", "instock" : 120 }
]
}
{
"_id" : 2,
"item" : "jkl",
"price" : 20,
"quantity" : 1,
"inventory_docs" : [
{ "_id" : 4, "sku" : "jkl", "description" : "product 4", "instock" : 70 }
]
}
{
"_id" : 3,
"inventory_docs" : [
{ "_id" : 5, "sku" : null, "description" : "Incomplete" },
{ "_id" : 6 }
]
}
回答by gustavohenke
Short answer:You can't.
简短的回答:你不能。
Long answer:In the Aggregation Framework, the returned fields are built by you, and you're able to "rename" document properties.
长答案:在聚合框架中,返回的字段由您构建,您可以“重命名”文档属性。
What this means is that Mongoose can't identify that your referenced documents will be available in the final result.
这意味着 Mongoose 无法确定您的参考文档将在最终结果中可用。
The best thing you can do in such a situation is populate the field you want after the query has returned. Yes, that would result in two DB calls, but it's what MongoDB allows us to do.
在这种情况下,您可以做的最好的事情是在查询返回后填充您想要的字段。是的,这会导致两次数据库调用,但这是 MongoDB 允许我们做的。
Somewhat like this:
有点像这样:
Appointments.aggregate([ ... ], function( e, result ) {
if ( e ) return;
// You would probably have to do some loop here, as probably 'result' is array
Patients.findOneById( result.patient, function( e, patient ) {
if ( e ) return;
result.patient = patient;
});
});
回答by Vidura Adikari
You have to do it in two, not in one statement.
你必须分两次做,而不是一次做。
In async awaitscenario, make sure awaituntil populate.
在异步等待场景中,确保等待直到填充。
const appointments = await Appointments.aggregate([...]);
await Patients.populate(appointments, {path: "patient"});
return appointments;
or (if you want to limit)
或(如果你想限制)
await Patients.populate(appointments, {path: "patient", select: {_id: 1, fullname: 1}});
回答by Himanshu sharma
domain.Farm.aggregate({
$match: {
"_id": mongoose.Types.ObjectId(farmId)
}
}, {
$unwind: "$SelfAssessment"
}, {
$match: {
"SelfAssessment.questionCategoryID": QuesCategoryId,
"SelfAssessment.questionID": quesId
}
},function(err, docs) {
var options = {
path: 'SelfAssessment.actions',
model: 'FarmAction'
};
domain.Farm.populate(docs, options, function (err, projects) {
callback(err,projects);
});
});
results i got action model populate
结果我得到了动作模型填充
{ "error": false, "object": [
{
"_id": "57750cf6197f0b5137d259a0",
"createdAt": "2016-06-30T12:13:42.299Z",
"updatedAt": "2016-06-30T12:13:42.299Z",
"farmName": "abb",
"userId": "57750ce2197f0b5137d2599e",
"SelfAssessment": {
"questionName": "Aquatic biodiversity",
"questionID": "3kGTBsESPeYQoA8ae2Ocoy",
"questionCategoryID": "5aBe7kuYWIEoyqWCWcAEe0",
"question": "Waterways protected from nutrient runoff and stock access through fencing, buffer strips and off stream watering points",
"questionImage": "http://images.contentful.com/vkfoa0gk73be/4pGLv16BziYYSe2ageCK04/6a04041ab3344ec18fb2ecaba3bb26d5/thumb1_home.png",
"_id": "57750cf6197f0b5137d259a1",
"actions": [
{
"_id": "577512c6af3a87543932e675",
"createdAt": "2016-06-30T12:38:30.314Z",
"updatedAt": "2016-06-30T12:38:30.314Z",
"__v": 0,
"Evidence": [],
"setReminder": "",
"description": "sdsdsd",
"priority": "High",
"created": "2016-06-30T12:38:30.312Z",
"actionTitle": "sdsd"
}
],
"answer": "Relevant"
},
"locations": []
} ], "message": "", "extendedMessage": "", "timeStamp": 1467351827979 }


