Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 如何从聚合(重新)分组中的第一个文档复制所有字段_Mongodb_Copy_Aggregation Framework_Grouping - Fatal编程技术网

Mongodb 如何从聚合(重新)分组中的第一个文档复制所有字段

Mongodb 如何从聚合(重新)分组中的第一个文档复制所有字段,mongodb,copy,aggregation-framework,grouping,Mongodb,Copy,Aggregation Framework,Grouping,在名为test的集合中,我有一些文档类似于: { "_id" : "PRQA2311", "name": "Binder", "category": "Office Supplies", "price": 3.99, "...": "...", "variant

在名为
test
的集合中,我有一些文档类似于:

{
    "_id" : "PRQA2311",
    "name": "Binder",
    "category": "Office Supplies",
    "price": 3.99,
    "...": "...",
    "variants" : [
        {
            "barcode" : "2314399903212",
            "attributes" : {
                "color" : "red",
                "size" : "Letter"
            }
        },
        {
            "barcode" : "2314399903213",
            "attributes" : {
                "color" : "red",
                "size" : "A4"
            }
        },
        {
            "barcode" : "2314399903214",
            "attributes" : {
                "color" : "blue",
                "size" : "Letter"
            }
        },
        {
            "barcode" : "2314399903215",
            "attributes" : {
                "color" : "blue",
                "size" : "A4"
            }
        }
    ]
}
我使用以下聚合管道对它们进行拆分和重组,使每个产品只有一种颜色:

db.test.aggregate([
{
$unwind:“$variants”
},
{
$group:{
_身份证:{
$concat:[
{“$toString”:“$\u id”},
".",
{“$toString”:“$variants.attributes.color”}
]
},
名称:{$first:$name},
变体:{$push:$variants}
}
}
]).pretty();
这很好,但我也想复制其他字段。而我可以通过显式地将字段添加到组聚合中来实现这一点,就像我对
name
字段所做的那样。如果我可以复制所有字段,那么开发和维护就会更容易

看看这个被接受的答案,似乎这在过去是不可能的。然而,第二个答案暗示,新版本的MongoDB可能会实现这一点,尽管提供的解决方案并不立即适用于我的问题

我认为使用
$mergeObjects
$replaceRoot
可能会有一个解决方案,但我还没有解决这个问题。

您可以将整个“root”文档()放在一个字段中,然后使用将其与
变体
字段合并

db.test.aggregate([
  {
    $unwind: "$variants"
  },
  {
    $group: {
      _id: {
        $concat: [
          { "$toString": "$_id" },
          ".",
          { "$toString": "$variants.attributes.color" }
        ]
      },
      variants: {
        $push: "$variants"
      },
      _root: {
        $first: "$$ROOT" // put all fields inside _root
      }
    }
  },
  {
    $replaceRoot: { // replace the root document with the combination of _root and variants, and _id if you want to keep the concatenated _id
      newRoot: {
        $mergeObjects: [
          "$_root",
          { _id: "$_id", variants: "$variants" }
        ]
      }
    }
  }
])

提示:对于MongoDB v4.2或更高版本,您可以使用
{$replaceWith:}
而不是
{$replaceRoot:{newRoot:}}
将整个“root”文档()放在一个字段中,然后使用将其与
变体
字段合并

db.test.aggregate([
  {
    $unwind: "$variants"
  },
  {
    $group: {
      _id: {
        $concat: [
          { "$toString": "$_id" },
          ".",
          { "$toString": "$variants.attributes.color" }
        ]
      },
      variants: {
        $push: "$variants"
      },
      _root: {
        $first: "$$ROOT" // put all fields inside _root
      }
    }
  },
  {
    $replaceRoot: { // replace the root document with the combination of _root and variants, and _id if you want to keep the concatenated _id
      newRoot: {
        $mergeObjects: [
          "$_root",
          { _id: "$_id", variants: "$variants" }
        ]
      }
    }
  }
])

提示:对于MongoDB v4.2或更高版本,您可以使用
{$replaceWith:}
而不是
{$replaceRoot:{newRoot:}
更新 我已经验证了这也有效,并且目前是我首选的方法,等待基准测试:

db.test.aggregate([
{
$unwind:“$variants”
},
{
$group:{
_身份证:{
$concat:[
{“$toString”:“$\u id”},
".",
{“$toString”:“$variants.attributes.color”}
]
},
对象:{$first:$$ROOT},
变体:{$push:$variants}
}
},
{
$set:{
“object.\u id”:“$\u id”,
“object.variants”:“$variants”,
}
},
{
$replaceRoot:{newRoot:$object}
}
]).pretty();

我明白了,不过我更喜欢

db.test.aggregate([
{
$unwind:“$variants”
},
{
$group:{
_身份证:{
$concat:[
{“$toString”:“$\u id”},
".",
{“$toString”:“$variants.attributes.color”}
]
},
对象:{$first:$$ROOT},
变体:{$push:$variants}
}
},
{
$unset:[“object.\u id”,“object.variants”]
},
{
$set:{
“object.\u id”:“$\u id”,
“object.variants”:“$variants”,
}
},
{
$replaceRoot:{newRoot:$object}
}
]).pretty();
更新 我已经验证了这也有效,并且目前是我首选的方法,等待基准测试:

db.test.aggregate([
{
$unwind:“$variants”
},
{
$group:{
_身份证:{
$concat:[
{“$toString”:“$\u id”},
".",
{“$toString”:“$variants.attributes.color”}
]
},
对象:{$first:$$ROOT},
变体:{$push:$variants}
}
},
{
$set:{
“object.\u id”:“$\u id”,
“object.variants”:“$variants”,
}
},
{
$replaceRoot:{newRoot:$object}
}
]).pretty();

我明白了,不过我更喜欢

db.test.aggregate([
{
$unwind:“$variants”
},
{
$group:{
_身份证:{
$concat:[
{“$toString”:“$\u id”},
".",
{“$toString”:“$variants.attributes.color”}
]
},
对象:{$first:$$ROOT},
变体:{$push:$variants}
}
},
{
$unset:[“object.\u id”,“object.variants”]
},
{
$set:{
“object.\u id”:“$\u id”,
“object.variants”:“$variants”,
}
},
{
$replaceRoot:{newRoot:$object}
}
]).pretty();

data:{$push:$$ROOT}而不是所有字段(例如名称、变量)怎么样。您将从以前的管道中获取所有字段?@Gibbs我实际上一直在使用类似的
“object”:{“$first”:“$$ROOT”}
,但是我仍然需要找出如何进行转换,以便字段最终位于正确的位置。我认为是$addFields或$mergeObjects后跟replaceRoot。但是我还没怎么走运。用
数据:{$push:$$ROOT}
代替所有字段,例如名称、变量,怎么样。您将从以前的管道中获取所有字段?@Gibbs我实际上一直在使用类似的
“object”:{“$first”:“$$ROOT”}
,但是我仍然需要找出如何进行转换,以便字段最终位于正确的位置。我认为是$addFields或$mergeObjects后跟replaceRoot。但是我还没有太多的运气。如果要覆盖这些,实际上不需要
$unset
fields@thammada.ts哇,太好了。事实上,我认为我可能会在没有未设置阶段的情况下使用我的答案,因为它更容易让人看到。虽然我是