例如,如果我有这样的一个文件。
{
a: 1,
subdoc: {
b: 2,
c: 3
}
}
我该如何将其转换为这样的格式?(不使用project
)
{
a: 1,
b: 2,
c: 3
}
{
a: 1,
subdoc: {
b: 2,
c: 3
}
}
我该如何将其转换为这样的格式?(不使用project
)
{
a: 1,
b: 2,
c: 3
}
$project
聚合框架管道运算符。这是推荐的方式。如果你不想使用project
,请查看链接。
以下是你的案例示例:db.collection.aggregation([{$project{ . . }}]);
db.collectionName.aggregate
([
{
$project: {
a: 1,
b: '$subdoc.b',
c: '$subdoc.c'
}
}
]);
{
"a" : 1,
"b" : 2,
"c" : 3
}
您可以使用$replaceRoot
,并将其与$addFields
阶段一起使用,如下所示:
db.collection.aggregate([
{ "$addFields": { "subdoc.a": "$a" } },
{ "$replaceRoot": { "newRoot": "$subdoc" } }
])
$$ROOT
和mergeObjects
函数进行合并,示例代码如下:db.collection.aggregate([
{$replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$subdoc"] } } },
{$project: { subdoc: 0 } },
])
注意不要改变原本的意思,并且使内容更加通俗易懂。 - 0zkr PM$replaceWith
($replaceRoot
的别名)以及$mergeObjects
运算符来实现这一点。let pipeline = [
{
"$replaceWith": {
"$mergeObjects": [ { "a": "$a" }, "$subdoc" ]
}
}
];
或者let pipeline = [
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [{ "a": "$a" }, "$subdoc" ]
}
}
}
];
db.collection.aggregate(pipeline)
您还可以在$mergeObjects
中使用$$ROOT
{ $replaceWith: {
$mergeObjects: [ "$$ROOT", "$subdoc" ]
} }
从 Mongo 4.2
开始,聚合操作符 $replaceWith
可以用来用另一个文档(在我们的情况下是子文档)替换文档,这相当于 @chridam 提到的 $replaceRoot
的简化语法。
因此,我们可以首先在子文档中包含根字段,以继续使用 $set
操作符(也是 Mongo 4.2
中 $addFields
的别名),然后使用 $replaceWith
将整个文档替换为子文档:
// { a: 1, subdoc: { b: 2, c: 3 } }
db.collection.aggregate([
{ $set: { "subdoc.a": "$a" } },
{ $replaceWith: "$subdoc" }
])
// { b: 2, c: 3, a: 1 }
db.mortgageRequests.aggregate( [
{ $unwind: "$arrayLevel1s" },
{ $unwind: "$arrayLevel1s.arrayLevel2s" },
{ $match: { "arrayLevel1s.arrayLevel2s.documentid" : { $eq: "6034bceead4ed2ce3951f38e" } } },
{ $replaceRoot: { newRoot: "$arrayLevel1s.arrayLevel2s" } }
] )
我想最简单的方法是在返回结果后使用map
进行修改。
collection.mapFunction = function(el) {
el.b = el.subdoc.b;
el.c = el.subdoc.c
delete(el.subdoc);
return el;
}
...
var result = await collection.aggregate(...).toArray();
result = result.map(collection.mapFunction);
db.collection.update({},{ $set: { "b": 2, "c": 3 }, $unset: { "subdoc": 1 } })
db.collection.find({ "subdoc": {"$exists": 1 } }).forEach(function(doc) {
var setDoc = {};
for ( var k in doc.subdoc ) {
setDoc[k] = doc.subdoc[k];
}
db.collection.update(
{ "_id": doc._id },
{ "$set": setDoc, "$unset": "subdoc" }
);
})
这也使用了一些安全的 $exists
用法,以确保您选择的文档中实际存在“subdoc”键。
$set
和 $unset
。我担心循环比 $project
的性能要差,对吗?如果是这样,我就坚持使用 $project
,但需要打更多的字(子文档中有30个以上的元素)。 - zachguo
project
意味着要输入很多内容。 - zachguo$replaceRoot
,它允许您将subdoc
作为新的$$ROOT
。但是,它会完全替换根文档。我不知道如何将subdoc
与原始根文档中已存在的字段合并。也许这可以给某些人提供提示... - maganap