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哇,太好了。事实上,我认为我可能会在没有未设置阶段的情况下使用我的答案,因为它更容易让人看到。虽然我是