2

我正在尝试通过 mongoose 3.6.20 进行排序,但我收到了一些意想不到的结果。

我有一个有名字的公司列表。起初我以为它可能是以区分大小写的方式排序。根据文章,我希望是真的。

我现在使用虚拟属性来降低排序字段的大小写。但是,我仍然得到意想不到的结果。

CompanySchema.virtual('name_lower').get(function(){
  return this.name.toLowerCase();
});

当我排序时

Company.find().sort({ name_lower: 1 });

我按以下顺序获取它:

  1. 公司名称
  2. 谷歌
  3. 公司名称(是的,用于测试的副本)

我也在输出我的虚拟财产的价值,它看起来是正确的。没有空格或时髦的字符会导致第二个“公司名称”出现在 google 之后。

使用 nodejs、express、mongoose。

我错过了什么或做错了什么?


更新:

根据答案中提供的信息,我重构了我的架构以包含一些规范化字段并连接到我的文档的预保存事件中,在此我更新这些规范化字段并在以后的所有查询中使用它们进行排序。

CompanySchema.pre('save', function(next){
  this.normalized_name = this.name;
});

接下来,在我使用的架构中:

var CompanySchema = mongoose.Schema({
  ...
  normalized_name: { type: String, set: normalize },
  ...
});

Wherenormalize是一个函数,它现在返回传递给它的值的小写版本。但是,这允许我稍后非常快速地对其进行扩展,并且我可以快速对可能需要排序的其他字段执行相同的操作。

4

4 回答 4

3

从 MongoDB v3.4 开始,可以使用排序方法完成不区分大小写的排序:

Company.find()
    .collation({locale: "en" }) //or whatever collation you want
    .sort({name:'asc'})
    .exec(function(err, results) {
        // use your case insensitive sorted results
    });
于 2017-03-20T06:50:29.553 回答
0

不幸的是 MongoDB 和 Mongoose 目前不支持复杂的排序,所以有 2 个选项:

  1. 如您所说,创建一个新字段,其名称已清理为全部小写
  2. 对所有数据运行一个大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()

请参阅使用 $toLowerMongoose 更新 MongoDB 集合:按字母顺序排序以获取更多信息。

于 2013-10-17T20:46:16.873 回答
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();
});
于 2014-10-06T10:05:01.693 回答
0

这个答案似乎对我更有帮助。我必须考虑变音符号以及案例,所以我使用了strength:3.

猫鼬:按字母顺序排序

于 2021-02-02T06:20:51.487 回答