我试图通过降序日期顺序对我的通知进行排序。我相信他们目前正在升序。我尝试了两种不同的方法来在我的填充语句中对通知进行排序
Notification.populate(user.notifications, { path: 'project', model: 'Project', sort: { 'created': -1 }},
function(err, notifications) {
// console.log('nested population of user', notifications);
socket.emit('take notifications', {
notifications: notifications,
num_unread: unread
});
});
Notification.populate(user.notifications, { path: 'project', model: 'Project', sort: { 'created': -1 }},
function(err, notifications) {
// console.log('nested population of user', notifications);
socket.emit('take notifications', {
notifications: notifications,
num_unread: unread
});
});
我也试过切换1和-1参数,但这没有做任何事情。
var NotificationSchema = new Schema({
created: {
type: Date,
default: Date.now
},
type: {
type: String,
enum: ['rfc']
},
read: {
type: Boolean,
default: false
},
from: {
type: Schema.ObjectId,
ref: 'User'
},
project: {
type: Schema.ObjectId,
ref: 'Project'
}
});
答案 0 :(得分:1)
这不是.populate()
形式与"sort"
选项一起使用的方式,因为该选项具有不同的预期用法。
您基本上只需要常规JavaScript Array.sort()
,或者因为您要排序的属性在填充之前已经在父文档中,那么只需将.sort()
光标修饰符应用于初始$lookup
1}}无论如何。
所以在.find()
查询中:
.find()
或使用Notification.find()
.populate({ path: 'project', model: 'Project'})
.sort({ "created": -1 })
.exec(function(err,notifications) {
// sorted by cursor
});
调用Model.populate()
数组内容:
Array.sort()
因此,根据您的情况,当前字段上的父项的Notification.populate(
user.notifications,
{ path: 'project', model: 'Project' },
function(err,notifications) {
notifications.sort(function(a,b) { return a.created < b.created });
// now it's sorted
}
)
而不是已填充的项目要么通过“游标”排序应用,要么只是对手中的常规数组进行排序。
考虑以下示例,其中这将是“用户”模型内容:
.sort()
然后有关于“追随者”项目的集合:
{
"_id" : ObjectId("5712ebbc37ba497f25b6b800"),
"name" : "Bill",
"sport" : ObjectId("5712e5af18a74c2810d5a5a8"),
"followers" : [
ObjectId("5712e001a83d6da651770e27"),
ObjectId("5712e05da83d6da651770e28"),
ObjectId("5712e06fa83d6da651770e29")
]
}
{
"_id" : ObjectId("5712ebbc37ba497f25b6b801"),
"name" : "Ted",
"sport" : ObjectId("5712e5da18a74c2810d5a5a9"),
"followers" : [
ObjectId("5712e001a83d6da651770e27"),
ObjectId("5712e06fa83d6da651770e29")
]
}
当然还有“运动”项目:
{ "_id": ObjectId("5712e001a83d6da651770e27"), "name": "Fred" },
{ "_id": ObjectId("5712e05da83d6da651770e28"), "name": "Sally" },
{ "_id": ObjectId("5712e06fa83d6da651770e29"), "name": "Abe" }
{ "_id" : ObjectId("5712e5af18a74c2810d5a5a8"), "name" : "Tennis" }
{ "_id" : ObjectId("5712e5da18a74c2810d5a5a9"), "name" : "Golf" }
的“排序”选项可用于处理“关注者”内容之类的内容,当填充此内容时,项目将反映“排序”的顺序,而不是它们发生的顺序。人口之前的数组内的序列。
因此,即使您为两个填充路径提供了“排序”选项,也只会对“数组”内容进行实际排序:
.populate()
结果将是:
User.populate(
users,
[
{ "path": "sport", "options": { "sort": { "name": 1 } } },
{ "path": "followers", "options": { "sort": { "name": 1 } } }
],
function(err,users) {
console.log(JSON.stringify(users,undefined,2));
callback(err);
}
);
这是正常行为,正如预期的那样。但是你要问的是“排序”由人口填充的属性返回的[
{
"_id": "5712ebbc37ba497f25b6b800",
"name": "Bill",
"sport": {
"_id": "5712e5af18a74c2810d5a5a8",
"name": "Tennis",
"__v": 0
},
"__v": 0,
"followers": [
{
"_id": "5712e06fa83d6da651770e29",
"name": "Abe",
"__v": 0
},
{
"_id": "5712e001a83d6da651770e27",
"name": "Fred",
"__v": 0
},
{
"_id": "5712e05da83d6da651770e28",
"name": "Sally",
"__v": 0
}
]
},
{
"_id": "5712ebbc37ba497f25b6b801",
"name": "Ted",
"sport": {
"_id": "5712e5da18a74c2810d5a5a9",
"name": "Golf",
"__v": 0
},
"__v": 0,
"followers": [
{
"_id": "5712e06fa83d6da651770e29",
"name": "Abe",
"__v": 0
},
{
"_id": "5712e001a83d6da651770e27",
"name": "Fred",
"__v": 0
}
]
}
]
列表。这是完全不同的事情,由数组上的常规客户端users
处理:
.sort()
实际上,实际上对列表进行排序就像排序任何常规数组一样。这是对填充属性进行排序的方式,因为人口实际上发生在客户端中。
在某些情况下,您确实希望在服务器上进行此类操作。这样的事情包括“分页”结果,将所有结果返回给客户端API然后在排序后只提取所需页面效率不高。
现在版本的MongoDB从v3.2.x开始向上包括$lookup
聚合管道方法。这基本上做 User.populate(
users,
[
{ "path": "sport", "options": { "sort": { "name": 1 } } },
{ "path": "followers", "options": { "sort": { "name": 1 } } }
],
function(err,users) {
users.sort(function(a,b) {
return a.sport.name > b.sport.name;
});
console.log(JSON.stringify(users,undefined,2));
callback(err);
}
);
在“客户端”上所做的事情,而不是“服务器”。
它没有所有相同的选项来过滤或直接从$lookup
“排序”项目,但由于这是在聚合框架中实现的,因此这些操作可以在不同的管道阶段执行。
包含一个示例列表,其中显示了使用.populate()
在客户端中处理.sort()
以及使用$lookup
的聚合管道技术。
两者都得出相同的结果,区别在于{{3}}是在返回客户端API之前需要对结果进行排序的技术,例如“分页”数据时。 / p>
.populate()
输出
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/follower');
var sportSchema = new Schema({
name: String
});
var followerSchema = new Schema({
name: String
});
var userSchema = new Schema({
name: String,
sport: { type: Schema.Types.ObjectId, ref: 'Sport' },
followers: [{ type: Schema.Types.ObjectId, ref: 'Follower' }]
});
var Sport = mongoose.model('Sport',sportSchema),
Follower = mongoose.model('Follower',followerSchema),
User = mongoose.model('User',userSchema);
async.series(
[
function(callback) {
async.each([Sport,Follower,User],function(model,callback) {
model.remove({},callback);
},callback);
},
function(callback) {
async.parallel(
[
function(callback) {
Sport.create([
{ "_id": "5712e5af18a74c2810d5a5a8", "name": "Tennis" },
{ "_id": "5712e5da18a74c2810d5a5a9", "name": "Golf" }
],callback);
},
function(callback) {
Follower.create([
{ "_id": "5712e001a83d6da651770e27", "name": "Fred" },
{ "_id": "5712e05da83d6da651770e28", "name": "Sally" },
{ "_id": "5712e06fa83d6da651770e29", "name": "Abe" }
],callback);
},
function(callback) {
User.create([
{
"name": "Bill",
"sport": "5712e5af18a74c2810d5a5a8",
"followers": [
"5712e001a83d6da651770e27",
"5712e05da83d6da651770e28",
"5712e06fa83d6da651770e29"
]
},
{
"name": "Ted",
"sport": "5712e5da18a74c2810d5a5a9",
"followers": [
"5712e001a83d6da651770e27",
"5712e06fa83d6da651770e29"
]
}
],callback);
}
],
callback
);
},
function(callback) {
console.log("Populate Output");
User.find().exec(function(err,users) {
if (err) callback(err);
User.populate(
users,
[
{ "path": "sport", "options": { "sort": { "name": 1 } } },
{ "path": "followers", "options": { "sort": { "name": 1 } } }
],
function(err,users) {
users.sort(function(a,b) {
return a.sport.name > b.sport.name;
});
console.log(JSON.stringify(users,undefined,2));
callback(err);
}
);
});
},
function(callback) {
console.log("Aggregate Output");
User.aggregate(
[
{ "$lookup": {
"from": "sports",
"localField": "sport",
"foreignField": "_id",
"as": "sport"
}},
{ "$unwind": "$sport" },
{ "$unwind": "$followers" },
{ "$lookup": {
"from": "followers",
"localField": "followers",
"foreignField": "_id",
"as": "followers"
}},
{ "$unwind": "$followers" },
{ "$sort": { "_id": 1, "followers.name": 1 } },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"sport": { "$first": "$sport" },
"followers": { "$push": "$followers" }
}},
{ "$sort": { "sport.name": 1 } }
],
function(err,users) {
console.log(JSON.stringify(users,undefined,2));
callback(err);
}
);
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);