MongoDB: 如何获取文档中的多个字段并将它们的值输出到一个数组中(作为一个新字段)?

MongoDB: How to take multiple fields within a document and output their values into an array (as a new field)?

MongoDB: 4.4.9, Mongosh: 1.0.4

我有一个 MongoDB 集合,其中包含完整的文档,其中月度生产数据作为单独的字段(monthlyProd1、monthlyProd2 等)。每个字段是一个月的生产数据,取值是object数据类型。

文档示例:

_id: ObjectId("314e0e088f183fb7e699d635")
name: "documentName"
monthlyProd1: Object
monthlyProd2: Object
monthlyProd3: Object
...

我想将所有月份放入一个新字段 (monthlyProd) -- 一个对象数组。

我似乎无法使用我尝试过的不同方法访问这些字段。例如,这接近于做我想做的事:

db.monthlyProdData.updateMany({}, 
    { $push: { "monthlyProd": { $each: [ "$monthlyProd1", "$monthlyProd2", "$monthlyProd3" ] } } }
) 

...但它并没有像我希望的那样从每个字段中获取值/对象数据,它只是将一个字符串输出到 monthlyProd 数组 ("$monthlyProd1", "$monthlyProd2", ...) :

实际输出:

monthlyProd: Array
    0:  "$monthlyProd1"
    1:  "$monthlyProd2"
    2:  "$monthlyProd3"
    ...

期望的输出:

monthlyProd: Array
    0:  Object
    1:  Object
    2:  Object
    ...

我要的是数据,不是字符串!哈哈。感谢您的帮助!

注:有些months/fields可能是空串(""),因为没有制作。我想确保不将空字符串添加到数组中——只有几个月的生产/字段具有对象数据类型。话虽如此,如果我可以访问这些字段的数据,我可以尝试自己解决这个问题!

试试这个:

db.collection.updateMany({}, [
  // convert to k-v Array
  { $set: { monthlyProd: { $objectToArray: "$$ROOT" } } },
  {
    $set: {
      monthlyProd: {
        // removed not needed objects
        $filter: {
          input: "$monthlyProd",
          cond: { $not: { $in: [ "$$this.k", [ "name", "_id" ] ] } }
          // or cond: { $in: [ "$$this.k", [ "monthlyProd1", "monthlyProd2", "monthlyProd3" ] ] }
        }
      }
    }
  },
  // output array value
  { $project: { monthlyProd: "$monthlyProd.v" } }
])

Mongo playground

感谢@Wernfried 对这个问题的原始解决方案。我已经修改了解决方案以合并我的 "Note" 关于忽略任何空的 monthlyProd# 值(也就是没有任何生产的月份),这样它们就不会添加到最终的 monthlyProd数组。

为此,我在 $filter 中的 cond: 中添加了一个 $and 运算符,并添加了以下内容作为 $and 运算符的第二个表达式(我使用 ""{} 处理空字段值(如果它们是字符串或对象数据类型):

{ $not: { $in: [ "$$this.v", [ "", {} ] ] } }

最终解:

db.monthlyProdData2.updateMany({}, [
  // convert to k-v Array
  { $set: { monthlyProd: { $objectToArray: "$$ROOT" } } },
  {
    $set: {
      monthlyProd: {
        // removed not needed objects
        $filter: {
          input: "$monthlyProd",
          cond: { $and: [
            { $not: { $in: [ "$$this.k", [ "name", "_id" ] ] } },
            { $not: { $in: [ "$$this.v", [ "", {} ] ] } }
          ]}
        }
      }
    }
  },
  // output array value
  { $project: { monthlyProd: "$monthlyProd.v", name: 1 } }
])

再次感谢@Wernfried 和 Whosebug 社区!