2015-05-12 20 views
5

Załóżmy mój Schemat wygląda tak:Jak zrobić „grupa przez” w mongoengine

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

Wyobraź mamy te istniejące kategorie: "avengers", "justice-leaguers", "villains" i chcę wykonać "group by" zapytanie do User.objects.all() tak, że mogę dostać coś takiego:

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

Albo jeszcze lepiej:

{ 
"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>] 
} 

Zajrzałem do dokumentacji MongoEngine i jeszcze nie znalazłem nic przydatnego. Dzięki chłopaki!

Odpowiedz

2

Używanie aggregation framework, trzeba tylko $group dokumentów według kategorii:

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

Korzystanie z funkcji $push agregacji, można zbudować tablicę zawierającą wszystkie nazwy użytkownika dzielenie tej samej kategorii.

wam dane przykładowe dane:

> 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" } 

To będzie produkują:

{ "_id" : "villains", "username" : [ "Ultron", "Joker", "LexLuthor" ] } 
{ "_id" : "justice-leagers", "username" : [ "Superman", "Batman" ] } 
{ "_id" : "avengers", "username" : [ "IronMan", "Thor", "Hulk" ] } 
+2

jakaś szansa, można to zrobić za pomocą Mongoengine? Bardzo prawdopodobne, że zrobię to w moim kodzie Pythona zamiast w powłoce Mongo. Dzięki jeszcze raz! – benjaminz

+0

@benjaminz Nie mam dostępu do Mongoengine (i nigdy go nie używałem), ale wydaje się, że ma wymagane API: [mongoengine.queryset.QuerySet.aggregate (* pipeline, ** kwargs)] (http: // docs.mongoengine.org/en/latest/apireference.html#mongoengine.queryset.QuerySet.aggregate) –

+0

Czy sprawdzić tę odpowiedź: [link] (http://stackoverflow.com/a/24420848/1882331) za korzystanie " grupy przez "w mongoengine. – Yahya

9

Ponieważ PO poprosił o mongoengine (i to, co potrzebne) Oto przykład tego, używając mongoengine:

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

Spowoduje to wyświetlenie iteratora kursora poleceń pymongo.

print list(categories) 

Wrócimy:

[{ "_id": "villains", "username": ["Ultron", "Joker", "LexLuthor"]}, 
{ "_id": "justice-leagers", "username": ["Superman", "Batman"]}, 
{ "_id": "avengers", "username": ["IronMan", "Thor", "Hulk"]}] 
+0

Nie działa. W ogóle nie jest to składnia pythonów. – SolessChong

+0

@SolessChong to właściwa składnia w porządku. Jest to lista słowników w języku Python. Powodem, dla którego nie działa, jest prawdopodobnie zmiana agregatu mongoengryny. Aby to działało, po prostu odrzuć listę: 'User.objects.aggregate ({...})' zamiast '([{...}])'. – Wtower

+0

@Wtower Zobacz edycję z 21 listopada. Odpowiedź poprawiła błąd składni. – SolessChong