MongoEngine Aggregation - сводный массив для объекта - PullRequest
0 голосов
/ 28 ноября 2018

Я работаю над следующими классами 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)

Не возвращает никакого результата.Кто-нибудь может помочь?

1 Ответ

0 голосов
/ 28 ноября 2018

Посмотрите, будет ли это для вас:

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

Идея состоит в том, чтобы $ раскрутить затем users, а затем $ group их через data который является key/value массивом для использования $ arrayToObject для формирования окончательного результата объект , за которым вы хотите.

Вы можете увидеть его здесьработая

...