在习惯了 SQL 之后,我遇到了 mongoDB 的这个问题。首先,我使用的是猫鼬。
现在,问题。我有一个名为User
.
var UserSchema = new Schema ({
id : ObjectId,
name : {type : String, trim : true, required : true},
email: {type:String, trim:true, required: true, index: { unique: true }},
password: {type:String, required: true, set: passwordToMD5},
age: {type:Number, min: 18, required: true, default: 18},
gender: {type: Number, default:0, required: true},
height: {type: Number, default:180, min: 140, max: 220},
_eye_color: {type: ObjectId, default: null},
location: {
lon: {type: Number, default: 0},
lat: {type: Number, default: 0}
},
status: {type:Number, required: true, default:0}
},{
toObject: { virtuals: true },
toJSON: { virtuals: true },
collection:"user"});
现在我需要从这个集合中选择所有用户并按特殊属性(比如“排名”)对它们进行排序。这个排名是根据他们与某个点的距离、年龄与给定年龄的比较等,用一定的逻辑计算出来的……
所以现在我想知道如何选择这个等级然后在排序中使用它?我曾尝试使用 virtuals,它们可以方便地计算附加信息,但不幸的是,无法find()
按虚拟字段对结果进行排序。当然我可以在虚拟中计算这个排名,然后选择所有记录,然后在回调中做一些javascript。但在这种情况下,当我选择所有用户然后排序然后限制时,javascript 部分可能需要太长时间......我正在考虑使用mapreduce,但我不确定它会做我想要的。如果我的任务可以在mongoDB/mongoose中完成,有人可以给我一个提示吗?
编辑 1
我也尝试过使用聚合框架,起初它似乎是具有该$project
能力的最佳解决方案。但是后来,当我需要进行排名计算时,我发现聚合不支持很多数学函数,如sin
,cos
和sqrt
。而且在投影中也不可能使用预定义的常用 javascript 函数。我的意思是,该函数被调用,但我无法将当前记录字段传递给它。
{$project: {
distance_from_user: mUtils.getDistance(point, this.location)
}
在函数内部,第二个属性是“未定义的”。
所以我想用聚合框架来做我的排名计算是不可能的。
编辑 2 好的,我知道每个人都告诉我不要使用 mapreduce,因为它不适合实时查询,但由于我不能使用聚合,我想我会尝试 mapreduce。所以假设我有这张地图减少。
function map() {
emit(1, // Or put a GROUP BY key here
{name: this.name, // the field you want stats for
age: this.age,
lat: this.location.lat,
lon: this.location.lon,
distance:0,
rank:0
});
}
function reduce(key, values) {
return val;
}
function finalize(key, value){
return value;
}
var command = {'mapreduce': "user", 'map': map.toString(), 'reduce': reduce.toString(), query:{$and: [{gender: user_params.gender}, {_id: {$ne: current_user_id}}]}, 'out': {inline:1}};
mongoose.connection.db.executeDbCommand(command, function(error, result){
if(error) {
log(error);
return;
}
log(result);
return;
});
我应该在 reduce(或者可能更改 map)中写什么来计算每个用户的排名?