2015-10-05 18 views
5

Mam kolekcję Mongo wiadomości, które wygląda tak:Mongo porządek na obliczoną stan

{ 
    'recipients': [], 
    'unRead': [], 
    'content': 'Text' 
} 

odbiorców jest tablicą identyfikatory użytkowników i nieprzeczytanych jest tablicą wszystkich użytkowników, którzy jeszcze nie otworzono wiadomość. Że działa zgodnie z przeznaczeniem, ale muszę zapytać listę wszystkich wiadomości tak, że zwraca pierwsze 20 wyników, ustalania priorytetów nieprzeczytane te pierwsze, coś takiego:

db.messages.find({recipients: {$elemMatch: userID} }) 
    .sort({unRead: {$elemMatch: userID}}) 
    .limit(20) 

Ale to nie działa. Jaki jest najlepszy sposób ustalania priorytetów wyników na podstawie tego, czy pasują do określonych kryteriów?

Odpowiedz

5

jeśli chcesz „masa” wyniki według określonych kryteriów lub ma jakiekolwiek „obliczonej wartości” w ramach „sort”, to trzeba metodę .aggregate() zamiast. Pozwala to na „przewidywany” wartości do stosowania w operacji $sort, na których tylko występuje pole w dokumencie można stosować:

db.messages.aggregate([ 
    { "$match": { "messages": userId } }, 
    { "$project": { 
     "recipients": 1, 
     "unread": 1, 
     "content": 1, 
     "readYet": { 
      "$setIsSubset": [ [userId], "$unread" ] } 
     } 
    }}, 
    { "$sort": { "readYet": -1 } }, 
    { "$limit": 20 } 
]) 

Tutaj $setIsSubset operatora umożliwia porównanie „nieprzeczytane” tablicy przeliczoną macierzy z [userId], aby sprawdzić, czy są jakieś dopasowania. Wynik będzie albo true, gdzie identyfikator użytkownika istnieje lub false, gdzie nie istnieje.

ten może być następnie przekazany do $sort, który nakazuje wyniki z preferencją do meczów (decending porządek znaczy true na górze), a na końcu $limit prostu zwraca wyniki do wysokości określonej.

Aby więc użyć wyliczonego terminu dla "sortowania", wartość musi być "rzutowana" na dokument, aby można było go posortować. Ramy agregacji to sposób, w jaki to robisz.

Należy również pamiętać, że nie jest wymagany, aby dopasować pojedynczą wartość w obrębie tablicy, a należy tylko bezpośrednio określić wartość. Jego celem jest spełnienie "wielu" warunków na pojedynczym elemencie tablicy, co oczywiście nie ma tu zastosowania.

+0

To działało idealnie. Dziękuję Ci! Jedyny komentarz, jaki zrobię, to fakt, że Mongo popełnił błąd, dopóki nie zmieniłem $ setIsSubSet na $ setIsSubset. – beatniknight

+0

@beatniknight Typowe mnie. Link do dokumentacji miał rację, ale mój mózg CamelCase ciągle mówi, że to dwa słowa i ciągle je pisze. –