【问题标题】:How to retrieve each single array element from mongo pipeline?如何从 mongo 管道中检索每个单个数组元素?
【发布时间】:2021-04-27 16:05:24
【问题描述】:

假设这是示例文档在 mongo-db 中的样子,

[
  {
    "_id": "1",
    "attrib_1": "value_1",
    "attrib_2": "value_2",
    "months": {
      "2": {
        "month": "2",
        "year": "2008",
        "transactions": [
          {
            "field_1": "val_1",
            "field_2": "val_2",
            
          },
          {
            "field_1": "val_4",
            "field_2": "val_5",
            "field_3": "val_6"
          },
          
        ]
      },
      "3": {
        "month": "3",
        "year": "2018",
        "transactions": [
          {
            "field_1": "val_7",
            "field_3": "val_9"
          },
          {
            "field_1": "val_10",
            "field_2": "val_11",
            
          },
          
        ]
      },
      
    }
  }
]

所需的输出是这样的,(我只是展示了第 2 个月和第 3 个月)

id months year field_1 field_2 field_3
1 2 2008 val_1 val_2
1 2 2008 val_4 val_5 val_6
1 3 2018 val_7 val_9
1 3 2018 val_10 val_11

我的尝试:

我在 Py-Mongo 中尝试过这样的事情,

pipeline = [
    {
        # some filter logic here to filter data basically first
    },
    {
        "$addFields": {
            "latest": {
                "$map": {
                    "input": {
                        "$objectToArray": "$months",
                    },
                    "as": "obj",
                    "in": {
                        "all_field_1" : {"$ifNull" : ["$$obj.v.transactions.field_1", [""]]},
                        "all_field_2": {"$ifNull" : ["$$obj.v.transactions.field_2", [""]]},
                        "all_field_3": {"$ifNull" : ["$$obj.v.transactions.field_3", [""]]},
                        "all_months" : {"$ifNull" : ["$$obj.v.month", ""]},
                        "all_years" : {"$ifNull" : ["$$obj.v.year", ""]},
                    }
                }
            }
        }
    },
    {
        "$project": {
            "_id": 1,
            "months": "$latest.all_months",
            "year":  "$latest.all_years",
            "field_1": "$latest.all_field_1",
            "field_2": "$latest.all_field_2",
            "field_3": "$latest.all_field_3",

        }
    }
]

# and I executed it as
my_db.collection.aggregate(pipeline, allowDiskUse=True)

以上内容实际上是带入数据,但它是将它们带入列表中。有没有办法在 mongo 本身中轻松地将它们每行带一个?

上面是这样带数据的,

id months year field_1 field_2 field_3
1 ["2", "3"] ["2008", "2018"] [["val_1", "val_4"], ["val_7", "val_10"]] [["val_2", "val_5"], ["", "val_11"]] [["", "val_6"], ["val_9", ""]]

非常感谢您就相同的事情以及更好的方法提供宝贵的意见!

感谢您的宝贵时间。

我的 Mongo 版本是 3.4.6,我使用 PyMongo 作为我的驱动程序。您可以在 mongo-db-playground

上查看正在执行的查询

【问题讨论】:

    标签: mongodb aggregation-framework pymongo aggregation


    【解决方案1】:

    在聚合查询中执行所有过程可能是个坏主意,您可以在客户端执行此操作,

    我创建了一个冗长的查询,可能会在大量数据中导致性能问题,

    • $objectToArraymonths 对象转换为数组
    • $unwind 解构月份数组
    • $unwind 解构transactions 数组并提供索引字段index
    • $group by _id, year, month and index,并从字段中的事务中获取第一个对象
    • $project 您可以根据需要设计您的回复,否则这是可选的,我已在操场链接中添加
    my_db.collection.aggregate([
      { # some filter logic here to filter data basically first },
      { $project: { months: { $objectToArray: "$months" } } },
      { $unwind: "$months" },
      {
        $unwind: {
          path: "$months.v.transactions",
          includeArrayIndex: "index"
        }
      },
      {
        $group: {
          _id: {
            _id: "$_id",
            year: "$months.v.year",
            month: "$months.v.month",
            index: "$index"
          },
          fields: { $first: "$months.v.transactions" }
        }
      }
    ], allowDiskUse=True);
    

    Playground

    【讨论】:

    • 有趣的想法。实际上,我试图将约 4-5M 记录扁平化为 CSV,而我分享的问题陈述实际上对我来说是一个障碍。你的方法给我带来的麻烦是我会用这些来链接我正在获取的其他细节。我想我将不得不使用查找重新加入它,因为在项目之后他们不会在那里。感谢您的帮助!
    • 你可以在 $group 阶段添加其他细节,只要提供细节会尽可能解决。
    • 感谢您的帮助!我会在一天左右的时间内尝试一下,看看我是否能解决问题,否则我一定会在这里联系你。再次感谢。
    • 所以我通过使用 unwind 和 addtofields 运算符让它工作,然后我对其进行迭代,它有点自动在单独的行中给我数据。
    猜你喜欢
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    相关资源
    最近更新 更多