创建复杂的解析服务器或 mongodb 查询
Create a complexe parse server or mongodb query
我正在使用 parse server + mongodb 作为后端,我需要帮助来创建复杂的查询:
首先这是我的数据库的架构:
friends
模型代表两个用户之间的友谊。
每个 user
都有一个 city
我想要实现的是创建函数,将 userId
作为输入和 return 城市列表 按朋友数量排序 .
这是我到目前为止的代码
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({})
}
所以问题是我无法在解析或 mongodb 中想出一种方法来加入这两个查询?
Parse 目前不支持聚合查询。这是一个如何使用 js sdk api 执行此操作的示例。如果你很好奇,为了确保这有效,在我检出的解析服务器版本中,我在 spec 目录中创建了一个 spec 文件,其中包含以下所有内容,然后我只关注测试 (通过在 'describe').
前面放置一个 'f'
/**
* 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);
});
});
我正在使用 parse server + mongodb 作为后端,我需要帮助来创建复杂的查询:
首先这是我的数据库的架构:
friends
模型代表两个用户之间的友谊。
每个 user
都有一个 city
我想要实现的是创建函数,将 userId
作为输入和 return 城市列表 按朋友数量排序 .
这是我到目前为止的代码
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({})
}
所以问题是我无法在解析或 mongodb 中想出一种方法来加入这两个查询?
Parse 目前不支持聚合查询。这是一个如何使用 js sdk api 执行此操作的示例。如果你很好奇,为了确保这有效,在我检出的解析服务器版本中,我在 spec 目录中创建了一个 spec 文件,其中包含以下所有内容,然后我只关注测试 (通过在 'describe').
前面放置一个 'f'/**
* 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);
});
});