MongoDB中不区分大小写的排序

时间:2014-04-08 08:08:24

标签: mongodb sorting mongodb-java

如何按特定字段对MongoDB集合进行排序,不区分大小写?默认情况下,我在a-z之前得到A-Z。

我正在使用Java。

10 个答案:

答案 0 :(得分:40)

排序确实像MongoDB中那样工作,但你可以使用aggregate实现这一点:

获取以下数据:

{ "field" : "BBB" }
{ "field" : "aaa" }
{ "field" : "AAA" }

所以使用以下声明:

db.collection.aggregate([
    { "$project": {
       "field": 1,
       "insensitive": { "$toLower": "$field" }
    }},
    { "$sort": { "insensitive": 1 } }
])

会产生如下结果:

{
    "field" : "aaa",
    "insensitive" : "aaa"
},
{
    "field" : "AAA",
    "insensitive" : "aaa"
},
{
    "field" : "BBB",
    "insensitive" : "bbb"
}

对于在转换时产生相同密钥的任何值,将保持实际的插入顺序。

答案 1 :(得分:37)

<强>更新 截至目前,mongodb有不区分大小写的索引:

Users.find({})
  .collation({locale: "en" })
  .sort({name: 1})
  .exec()
  .then(...)

壳:

db.getCollection('users')
  .find({})
  .collation({'locale':'en'})
  .sort({'firstName':1})

更新:此答案已过期,3.4将包含不区分大小写的索引。请查看JIRA以获取更多信息https://jira.mongodb.org/browse/SERVER-90


不幸的是,MongoDB还没有不区分大小写的索引:https://jira.mongodb.org/browse/SERVER-90并且任务已被推回。

这意味着当前对不区分大小写进行排序的唯一方法是实际创建一个特定的“低级”字段,复制有问题的排序字段的值(当然是较低的字段),然后对其进行排序。

答案 2 :(得分:13)

这在MongoDB JIRA上已经很长一段时间issue,但现在已经解决了。看看this release notes for detailed documentation。您应该使用collation

User.find()
    .collation({locale: "en" }) //or whatever collation you want
    .sort({name:'asc'})
    .exec(function(err, users) {
        // use your case insensitive sorted results
    });

答案 3 :(得分:2)

到目前为止(mongodb 4),您可以执行以下操作:

mongo shell:

db.getCollection('users')
  .find({})
  .collation({'locale':'en'})
  .sort({'firstName':1});

猫鼬:

Users.find({})
  .collation({locale: "en" })
  .sort({name: 1})
  .exec()
  .then(...)

这里是mongodb的supported languages and locales

答案 4 :(得分:1)

这是Java版。我混合了BasicDBObject的no-args和第一个key-val变体只是为了变种

        DBCollection coll = db.getCollection("foo");

        List<DBObject> pipe = new ArrayList<DBObject>();

        DBObject prjflds = new BasicDBObject();
        prjflds.put("field", 1);
        prjflds.put("insensitive", new BasicDBObject("$toLower", "$field"));

        DBObject project = new BasicDBObject();
        project.put("$project", prjflds);
        pipe.add(project);

        DBObject sort = new BasicDBObject();
        sort.put("$sort", new BasicDBObject("insensitive", 1));
        pipe.add(sort);

        AggregationOutput agg = coll.aggregate(pipe);

        for (DBObject result : agg.results()) {
            System.out.println(result);
        }

答案 5 :(得分:1)

如果要对文档中的所有数据进行排序并返回,可以添加document: "$$ROOT"

db.collection.aggregate([
  { 
    $project: {
      field: 1,
      insensitive: { $toLower: "$field" },
      document: "$$ROOT"
    }
  },
  { $sort: { insensitive: 1 } }
]).toArray()

答案 6 :(得分:0)

添加代码.collation({'locale':'en'})帮助解决了我的问题。

答案 7 :(得分:0)

在猫鼬中:-

Customer.find()
  .collation({locale: "en" })
  .sort({comapany: 1})

答案 8 :(得分:0)

尝试以上所有方法并回答 合并结果

答案1:

db.collection.aggregate([
    { "$project": {
       "field": 1,
       "insensitive": { "$toLower": "$field" }
    }},
    { "$sort": { "insensitive": 1 } } ])

聚集查询将字段转换为较低字段,因此对于大数据而言性能较低。

答案2:

db.collection.find({}).collation({locale: "en"}).sort({"name":1})

默认情况下,mongo遵循uft-8编码(Z具有较高的优先级,然后是a)规则,因此应使用特定于语言的规则进行覆盖。 与上面的查询相比,它的快速比较 查看正式文档以自定义规则

https://docs.mongodb.com/manual/reference/collation/

答案 9 :(得分:-2)

我们借助JavaScript数组中的.sort函数来解决这个问题

这是代码


    function foo() {
      let results = collections.find({
        _id: _id
      }, {
        fields: {
          'username': 1,
        }
      }).fetch();

      results.sort((a, b)=>{
        var nameA = a.username.toUpperCase();
        var nameB = b.username.toUpperCase();

        if (nameA  nameB) {
          return 1;
        }
        return 0;
      });

      return results;
    }