【问题标题】:MongoDB: How to take multiple fields within a document and output their values into an array (as a new field)?MongoDB:如何获取文档中的多个字段并将它们的值输出到数组中(作为新字段)?
【发布时间】:2021-09-25 20:23:08
【问题描述】:

MongoDB:4.4.9,Mongosh:1.0.4

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

文档示例:

_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
    ...

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

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

【问题讨论】:

    标签: arrays mongodb field mongo-shell


    【解决方案1】:

    试试这个:

    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

    【讨论】:

    • 谢谢,效果很好!我见过 objectToArray 运算符,但我希望避免这种更复杂的管道(无论如何对我来说更复杂)。我还删除了最后一个 $project 行,以便保留原始数据。
    • 我对访问文档字段/值有些困惑。你能解释一下为什么“$field”在某些情况下似乎可以访问字段的值,而不是我的 $push 示例吗?
    • 更新:我意识到 $project 行是必要的,因此只有值/对象存储在数组中,所以我把它带回来并明确说明我想保留哪些其他字段。例如:{ $project: {monthlyProd: "$monthlyProd.v", name: 1 } }
    【解决方案2】:

    感谢 @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 和 Stackoverflow 社区!

    【讨论】:

      猜你喜欢
      • 2021-01-08
      • 2019-10-25
      • 1970-01-01
      • 2021-06-24
      • 2021-09-07
      • 1970-01-01
      • 2020-07-29
      • 2021-04-05
      • 2022-01-08
      相关资源
      最近更新 更多