首页 > 解决方案 > MongoEngine 聚合 - 将数组透视到对象

问题描述

我正在关注 MongoEngine 课程

class User(Document):
    username = EmailField(primary_key=True)
    name = StringField()

class Asset(Document):
    users = ListField( ReferenceField("User") )
    remote = MapField( DynamicField() )

上述类的示例文件是

用户:

{
    "_id" : "xyz@xyz.com",
    "name" : "xyz"
}

资产:

{
    "_id" : ObjectId("5485asasansja"),
    "users" : ["xyz@xyz.com", "abc@abc.com"],
    "remote" : { "bytes" : 123,
                  "source" : "some source"
               }
},
{
    "_id" : ObjectId("5885asaskaia"),
    "users" : ["pqr@xyz.com", "abc@abc.com"],
    "remote" : { "bytes" : 345,
                  "source" : "another source"
               }
}

我想使用管道获得结果

{
    "xyz@xyz.com" : {"some source": 45845, "another source": 5845},
    "abc@abc.com" : {"some source": 584, "another source": 986}
}

底线,想要根据每个用户的来源获取字节总和。

我试过了

pipeline = [

        {'$project':
             {'remote.source': 1, 'remote.bytes': 1 }},

        {'$unwind': '$users'},

        {'$lookup': {
            'from': 'user', 'localField': 'users', 'foreignField' : '_id', 'as':'user'
        }},

        {'$match': {'remote.source': {'$exists': True, '$ne': None}}},
        {'$project': {'username': '$user.username'}},

        {'$group':
             {'username':'$username','source': '$remote.source', 'count': {'$sum': 1}, 'size': {'$sum': '$remote.bytes'}}}
    ]

for each in Asset.objects().aggregate(*pipeline):
    print(each)

它不返回任何结果。任何人都可以帮忙吗?

标签: mongodbmongodb-queryaggregation-frameworkmongoengine

解决方案


看看这是否适合你:

db.collection.aggregate([
  { $unwind: "$users" },
  {
    "$group": {
      "_id": null,
      "data": {
        "$push": {
          "k": "$users",
          "v": "$remote"
        }
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$arrayToObject": "$data"
      }
    }
  }
])

这个想法是通过$ unwindusers然后$group它们data是一个key/value数组,以便使用$arrayToObject来形成您所追求的最终输出对象

你可以在这里看到它的工作


推荐阅读