我在mongodb中使用了一些聚合函数。 我想获取书籍作者文档中的文档,其中只有书籍ID作为字符串数组,如下所示:
作者文件
{
"_id" : "10",
"full_name" : "Joi Dark",
"books" : ["100", "200", "351"],
}
和其他文件(书籍):
{
"_id" : "100",
"title" : "Node.js In Action",
"ISBN" : "121215151515154",
"date" : "2015-10-10"
}
所以结果我想要这个:
{
"_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"
}
],
}
答案 0 :(得分:2)
使用$lookup
根据from
与localField
的匹配来检索foreignField
中指定馆藏的数据:
db.authors.aggregate([
{ "$lookup": {
"from": "$books",
"foreignField": "_id",
"localField": "books",
"as": "books"
}}
])
as
是文档中编写"数组"的位置。包含相关文件。如果指定现有属性(例如此处完成),则该属性将被输出中的新数组内容覆盖。
如果您在MongoDB 3.4之前有MongoDB,那么您可能需要"books"
localField
数组作为db.authors.aggregate([
{ "$unwind": "$books" },
{ "$lookup": {
"from": "$books",
"foreignField": "_id",
"localField": "books",
"as": "books"
}}
])
首先:
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" }
}}
])
为原始文档中的每个数组成员创建一个新文档,因此再次使用$unwind
和$unwind
创建原始表单:
_id
实际上,如果ObjectId
类型的外国集合中的localField
值,但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 = [];
}
中的值为"字符串"那个版本,然后你需要转换数据,以便类型匹配。没有其他办法。
通过shell运行类似的东西进行转换:
"books"
这会将ObjectId
数组中的所有值转换为可在$lookup
操作中实际匹配的实际{{1}}值。