我正在尝试通过mongoose 3.6.20排序,我收到了一些意想不到的结果。
我有一个名字公司的名单。起初我以为可能是以区分大小写的方式排序。根据文章,我预计是真的。
我现在正在使用虚拟属性来排序排序字段。但是,我仍然会得到意想不到的结果。
CompanySchema.virtual('name_lower').get(function(){
return this.name.toLowerCase();
});
当我排序
Company.find().sort({ name_lower: 1 });
我按以下顺序得到它:
我也在输出我的虚拟财产的价值,看起来是正确的。没有空格或时髦字符会导致第二个“公司名称”出现在谷歌之后。
使用nodejs,express,mongoose。
我错过了什么或做错了什么?
更新
根据答案中提供的信息,我重构了我的架构以包含一些规范化字段并挂钩到我的文档的预存储事件,在那里我更新这些规范化字段并在将来的所有查询中使用它们进行排序。
CompanySchema.pre('save', function(next){
this.normalized_name = this.name;
});
接下来,在我使用的架构中:
var CompanySchema = mongoose.Schema({
...
normalized_name: { type: String, set: normalize },
...
});
其中normalize
是一个函数,现在返回传递给它的值的小写版本。但是,这允许我在以后快速扩展它,并且我可以快速地对我可能需要排序的其他字段做同样的事情。
答案 0 :(得分:2)
从MongoDB v3.4开始,可以使用collation方法完成不区分大小写的排序:
Company.find()
.collation({locale: "en" }) //or whatever collation you want
.sort({name:'asc'})
.exec(function(err, results) {
// use your case insensitive sorted results
});
答案 1 :(得分:0)
不幸的是,MongoDB和Mongoose目前不支持复杂排序,因此有两个选项:
对所有数据运行一个大for
循环,并将每个公司名称更新为小写形式:
db.CompanyCollection.find().forEach(
function(e) {
e.CompanyName = e.CompanyName.toLowerCase();
db.CompanyCollection.save(e);
}
)
或
db.CompanyCollection.update({_id: e._id}, {$set: {CompanyName: e.CompanyName.toLowerCase()
有关详细信息,请参阅Update MongoDB collection using $toLower和Mongoose: Sort alphabetically。
答案 2 :(得分:0)
我想在这个钩子中说出来:
CompanySchema.pre('save', function(next){
this.normalized_name = this.name;
});
如果您希望将next();
保存在数据库中,则必须在最后调用normalized_name
,因此预保存挂钩将如下所示:
CompanySchema.pre('save', function(next){
this.normalized_name = this.name;
next();
});
答案 3 :(得分:0)
这个答案似乎对我更有帮助。我不得不在案例中考虑变音符号,所以我使用了 strength:3
。