Jah*_*mad 4 mongodb mongodb-query aggregation-framework
我正在为 mongodb 中的一些聚合函数苦苦挣扎。我想在作者的文档中获取书籍文档,该文档只有书籍 id 作为字符串 id 数组,如下所示:
作者文档
{
"_id" : "10",
"full_name" : "Joi Dark",
"books" : ["100", "200", "351"],
}
Run Code Online (Sandbox Code Playgroud)
和其他文件(书籍):
{
"_id" : "100",
"title" : "Node.js In Action",
"ISBN" : "121215151515154",
"date" : "2015-10-10"
}
Run Code Online (Sandbox Code Playgroud)
所以结果我想要这个:
{
"_id" : "10",
"full_name" : "Joi Dark",
"books" : [
{
"_id" : "100",
"title" : "Node.js In Action",
"ISBN" : "121215151515154",
"date" : "2015-10-10"
},
{
"_id" : "200",
"title" : "Book 2",
"ISBN" : "1212151454515154",
"date" : "2015-10-20"
},
{
"_id" : "351",
"title" : "Book 3",
"ISBN" : "1212151454515154",
"date" : "2015-11-20"
}
],
}
Run Code Online (Sandbox Code Playgroud)
使用$lookup它在检索从被提名的收集数据from基础上的匹配localField到foreignField:
db.authors.aggregate([
{ "$lookup": {
"from": "$books",
"foreignField": "_id",
"localField": "books",
"as": "books"
}}
])
Run Code Online (Sandbox Code Playgroud)
这as是在文档中写入包含相关文档的“数组”的位置。如果您指定现有属性(例如此处完成),则该属性将被输出中的新数组内容覆盖。
如果您在 MongoDB 3.4 之前有一个 MongoDB,那么您可能需要$unwind将数组"books"作为第localField一个:
db.authors.aggregate([
{ "$unwind": "$books" },
{ "$lookup": {
"from": "$books",
"foreignField": "_id",
"localField": "books",
"as": "books"
}}
])
Run Code Online (Sandbox Code Playgroud)
它为原始文档中的每个数组成员创建一个新文档,因此$unwind再次使用并$group创建原始表单:
db.authors.aggregate([
{ "$unwind": "$books" },
{ "$lookup": {
"from": "$books",
"foreignField": "_id",
"localField": "books",
"as": "books"
}},
{ "$unwind": "$books" },
{ "$group": {
"_id": "$_id",
"full_name": { "$first" "$full_name" },
"books": { "$push": "$books" }
}}
])
Run Code Online (Sandbox Code Playgroud)
如果实际上您的_id值在ObjectId类型的外部集合中,但是您的值是该localField类型的“字符串”版本,那么您需要转换数据以使类型匹配。没有其他办法。
通过 shell 运行类似这样的东西来转换:
var ops = [];
db.authors.find().forEach(doc => {
doc.books = doc.books.map( book => new ObjectId(book.valueOf()) );
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": { "books": doc.books }
}
}
});
if ( ops.length >= 500 ) {
db.authors.bulkWrite(ops);
ops = [];
}
});
if ( ops.length > 0 ) {
db.authors.bulkWrite(ops);
ops = [];
}
Run Code Online (Sandbox Code Playgroud)
这会将"books"数组中的所有值转换为ObjectId可以在$lookup操作中实际匹配的实际值。
| 归档时间: |
|
| 查看次数: |
5209 次 |
| 最近记录: |