2017-03-23 10 views
0

Ich verwende parse server + mongodb für Back-End und ich brauche Hilfe eine komplexe Abfrage für die Erstellung von:erstellen complexe Parse-Server oder mongodb Abfrage

Zuerst ist hier ein Schema für meine db: enter image description here

Die friends Modell repräsentieren die Freundschaft zwischen zwei Benutzern. Jeder user hat ein city

Was ich versuche zu erreichen Funktion zu erstellen, die eine userId als Eingabe und Rück Liste der Städte sortiert nach Anzahl der Freunde.

Hier ist mein Code bis jetzt

function getCities(userId) { 

    //This query allow to count number of friends in a given city 
    var innerQuery1 = new Parse.Query(Friends); 
    innerQuery1. equalTo("user1", userId); 

    var innerQuery2 = new Parse.Query(Friends); 
    innerQuery2.equalTo("user2", userId); 

    countFriendsQueryInCity = Parse.Query.or(innerQuery1, innerQuery2); 
    countFriendsQueryInCity.equalTo("city", cityId) 
    countFriendsQueryInCity.count({..}) 

    //This to get all cities 
    var query = new Parse.Query(City); 
    query.find({}) 

} 

So ist die probleme ich kann nicht einen Weg Weg in Parse oder mongodb herauszufinden, die zwei Abfragen zu verbinden?

Antwort

2

Parse unterstützt zur Zeit keine Aggregationsabfragen. Hier ist ein Beispiel, wie Sie dies mit der js sdk api tun können. Falls Sie neugierig sind, um sicherzustellen, dass dies funktioniert, habe ich in meiner ausgecheckten Version des Parse-Server-Repos eine Spec-Datei im Spec-Verzeichnis mit allen folgenden Elementen erstellt und mich dann auf den Test konzentriert (indem man ein "f" vor "beschreiben" setzt.

/** 
* Return a sorted list of cities with count of friends in that city 
* 
* @param userId id of the user to build the list for 
* @returns an array of city, count pairs sorted descending 
*/ 
const getCities = function getCities(userId) { 
    const aggregation = {}; 
    const userPointer = new Parse.Object('Person').set('objectId', userId); 
    return new Parse.Query('Friend') 
    .equalTo('user1', userPointer) 
    .include('user2.city') 
    .each((friendship) => { 
     const city = friendship.get('user2').get('city').get('name'); 
     if (aggregation[city]) { 
     aggregation[city]++ 
     } 
     else { 
     aggregation[city] = 1; 
     } 
    }) 
    .then(() => { 
     const sortable = []; 
     for (const city in aggregation) { 
     sortable.push([city, aggregation[city]]); 
     } 
     return sortable.sort((a, b) => b[1] - a[1]); // desc 
    }); 
} 


// the unit test for the function above.... 
fdescribe('play with aggregations',() => { 
    it('should count friends by city and order desc', (done) => { 

    // create cities 
    const ny = new Parse.Object('City').set('name', 'ny'); 
    const sf = new Parse.Object('City').set('name', 'sf'); 

    // create some people to befriend 
    const people = [ 
     new Parse.Object('Person').set('city', ny), 
     new Parse.Object('Person').set('city', sf), 
     new Parse.Object('Person').set('city', sf), 
     new Parse.Object('Person').set('city', sf), 
    ]; 

    // the object of these friendships 
    const friendee = new Parse.Object('Person').set('city', sf); 

    // make the friendships 
    const friends = people.map(person => 
     new Parse.Object('Friend') 
     .set('user1', friendee) 
     .set('user2', person)); 

    // just saving the friends will save the friendee and cities too! 
    Parse.Object.saveAll(friends) 
     // all saved, now call our function 
     .then(() => getCities(friendee.id)) 
     .then((result) => { 
     const lastResult = result.pop(); 
     const firstResult = result.pop(); 
     expect(lastResult[0]).toBe('ny'); 
     expect(lastResult[1]).toBe(1); 
     expect(firstResult[0]).toBe('sf'); 
     expect(firstResult[1]).toBe(3); 
     done(); 
     }) 
     .catch(done.fail); 
    }); 
}); 
+0

Vielen Dank! Also bekommst du eine Liste aller Benutzerfreunde, dann fährst du die Freundesliste und machst die Zählung der Stadt, dass es ?? Auch was Wenn der Benutzer Tausende von Freunden haben, wird es zu kompliziert, weil Parsen nicht mehr als 1000 Artikel pro Seite verarbeiten kann? – Chlebta

+0

Parse.Query.each() hat kein Limit. Es wird durch alle von ihnen laufen. Das Problem wäre, wenn es Hunderttausende oder Millionen wären, könnte es die Verbindung abbrechen. die Alternative wäre, einen "BeforeSave" Hook auf der "Friend" -Klasse zu machen und speichern Sie die Aggregation bei speichern, anstatt es bei Bedarf zu suchen. So könnte man etwas wie eine FriendCityCount-Klasse haben, die userid, city, count als Spalten hat ... –

+0

Ich dachte darüber nach, aber das fügt eine weitere Tabelle hinzu, andere Funktionen ... Es ist verdrahtet, warum NoSql nicht unterstützt Join Abfrage – Chlebta