Как да групирате по в mongoengine

Да предположим, че моята схема изглежда така:

class User(Document):
  username = StringField()
  password = StringField()
  category = StringField()

Представете си, че имаме тези съществуващи категории: "avengers", "justice-leaguers", "villains" и искам да изпълня "group by" заявка за User.objects.all(), за да мога да получа нещо подобно:

[
 [<User: IronMan object>, <User: Thor object>, <User: Hulk object>], 
 [<User: Superman object>,<User: Batman object>], 
 [<User: Ultron object>, <User: Joker object>, <User: LexLuthor object>]
]

Или още по-добре:

{
 "avengers": [<User: IronMan object>, <User: Thor object>, <User: Hulk object>], 
 "justice-leaguers": [<User: Superman object>,<User: Batman object>], 
 "villains": [<User: Ultron object>, <User: Joker object>, <User: LexLuthor object>]
}

Разгледах документите на MongoEngine и все още не съм намерил нищо полезно. Благодаря момчета!


person benjaminz    schedule 12.05.2015    source източник


Отговори (2)


Използвайки рамката за агрегиране, трябва само да $group документи по категория:

db.User.aggregate([
  {
    $group: { _id: "$category", username: { $push: "$username" }}
  }
])

С помощта на функцията за агрегиране $push ще изградите масив, съдържащ всички потребителското име споделя същата категория.

Дадени са ви примерни данни:

> db.User.find({},{category:1,username:1,_id:0})
{ "category" : "avengers", "username" : "IronMan" }
{ "category" : "avengers", "username" : "Thor" }
{ "category" : "avengers", "username" : "Hulk" }
{ "category" : "justice-leagers", "username" : "Superman" }
{ "category" : "justice-leagers", "username" : "Batman" }
{ "category" : "villains", "username" : "Ultron" }
{ "category" : "villains", "username" : "Joker" }
{ "category" : "villains", "username" : "LexLuthor" }

Това ще доведе до:

{ "_id" : "villains", "username" : [ "Ultron", "Joker", "LexLuthor" ] }
{ "_id" : "justice-leagers", "username" : [ "Superman", "Batman" ] }
{ "_id" : "avengers", "username" : [ "IronMan", "Thor", "Hulk" ] }
person Sylvain Leroux    schedule 12.05.2015
comment
Има ли шанс това да се направи с помощта на Mongoengine? Много е вероятно да направя това в моя код на Python вместо в mongo shell. Благодаря отново! - person benjaminz; 12.05.2015
comment
@benjaminz Нямам достъп до Mongoengine (и никога не съм го използвал), но изглежда, че има необходимия API: mongoengine.queryset.QuerySet.aggregate(*pipeline, **kwargs) - person Sylvain Leroux; 12.05.2015
comment
Вижте този отговор: връзка за използване на „групиране по“ в mongoengine. - person Yahya; 31.05.2016
comment
Възможно ли е да добавите условия where в тези заявки? - person technazi; 27.06.2019

Тъй като OP поиска mongoengine (и това ми трябваше), ето пример за това с помощта на mongoengine:

categories = User.objects.aggregate([{
    '$group': { '_id': '$category', 'username': { '$push': '$username' }}
}])

Това ще върне итератор на курсора на командата pymongo.

print list(categories)

Ще се върне:

[{ "_id": "villains", "username": ["Ultron", "Joker", "LexLuthor"]},
 { "_id": "justice-leagers", "username": ["Superman", "Batman"]},
 { "_id": "avengers", "username": ["IronMan", "Thor", "Hulk"]}]
person Realistic    schedule 01.11.2015
comment
@SolessChong това е правилен синтаксис, наред. Това е списък от речници на Python. Причината, поради която вече не работи, вероятно е промяна в агрегата на mongoengine. За да работи, просто отхвърлете списъка: User.objects.aggregate({...}) вместо ([{...}]). - person Wtower; 16.12.2016
comment
@Wtower Вижте редакцията на 21 ноември. Отговорът е коригирал синтактична грешка. - person SolessChong; 19.12.2016
comment
@SolessChong добре, благодаря, че изясни това. Въпреки това коментарът по отношение на списъка е приложим в момента. - person Wtower; 19.12.2016
comment
@Realistic, благодаря за отговора! Имате ли нещо против да го актуализирате със синтаксиса на пример, когато имате повече от една категория, по която да групирате. Това е, което би работило в CLI $group : {_id : {one:"$one", two:"$two"}, но кодът казва, че не може да кодира обекта. - person hebeha; 24.12.2017