Mongodb 聚合使用ID的文档填充ID数组
我正在使用mongodb中的一些聚合函数。 我想在作者的文档中获取books文档,该文档只有books ID作为字符串数组ID,如下所示: 作者文档Mongodb 聚合使用ID的文档填充ID数组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我正在使用mongodb中的一些聚合函数。 我想在作者的文档中获取books文档,该文档只有books ID作为字符串数组ID,如下所示: 作者文档 { "_id" : "10", "full_name" : "Joi Dark", "books" : ["100", "200", "351"], } 和其他文件(书籍): 因此,我希望这样: { "_id" : "10", "full_name" : "Joi Dark", "books" : [ {
{
"_id" : "10",
"full_name" : "Joi Dark",
"books" : ["100", "200", "351"],
}
和其他文件(书籍):
因此,我希望这样:
{
"_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"
}
],
}
用于根据本地字段
与外来字段
的匹配,从中的指定集合中检索数据:
db.authors.aggregate([
{ "$lookup": {
"from": "$books",
"foreignField": "_id",
"localField": "books",
"as": "books"
}}
])
as
是在文档中写入包含相关文档的“数组”的位置。如果指定现有属性(如此处所述),则输出中的新数组内容将覆盖该属性
如果您在MongoDB 3.4之前有一个MongoDB,那么您可能需要首先将“books”
数组设置为本地字段
:
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" }
}}
])
如果事实上您的\u 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 = [];
}
这将把“books”
数组中的所有值转换为真正的ObjectId
值,这些值在$lookup
操作中可以实际匹配。如果不起作用,请返回空数组。books文档有_id键入的ObjectId,但在authors文档中,我只将id保存为字符串。@JahangirAhmad那么您需要修复它。您的问题在两个字段中都显示“字符串”。因此,请修复您的数据,使“object id like”字符串实际成为ObjectId
值。你需要帮助吗?请更新您的问题以显示真实数据。我所说的“更新”是指“除此之外”,不要覆盖您在原始问题中输入的数据。所以我把你的复习卷退了。得到答案后,不要更改所问问题的上下文。@JahangirAhmad您无法将字符串与对象ID
匹配。您需要帮助了解如何转换它们吗?如果你这样做了,那就问。停止编辑问题。是,请帮助我转换that@JahangirAhmad为运行转换添加了一个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 = [];
}