Javascript 在MongoDB中按字母顺序对文档进行排序(也称为自然排序顺序,人类排序)

Javascript 在MongoDB中按字母顺序对文档进行排序(也称为自然排序顺序,人类排序),javascript,mongodb,mongodb-query,natural-sort,Javascript,Mongodb,Mongodb Query,Natural Sort,我想了解如何使用MongoDB实现这一点 我有名称为“file1”、“file2”、“file22”、“file11”的文档(名称可以是任何形式,没有特定的模式) 我运行查询以按名称对所有文档进行排序,结果与预期不符 > db.mydata.find().sort({"name":1});

我想了解如何使用MongoDB实现这一点

我有名称为“file1”、“file2”、“file22”、“file11”的文档(名称可以是任何形式,没有特定的模式) 我运行查询以按名称对所有文档进行排序,结果与预期不符

> db.mydata.find().sort({"name":1});                                                                                                                          
{ "_id" : ObjectId("571e5a787e88d30b20b7857c"), "name" : "file1" }                                                                                            
{ "_id" : ObjectId("571e5a8c7e88d30b20b7857d"), "name" : "file11" }                                                                                           
{ "_id" : ObjectId("571e5a977e88d30b20b7857f"), "name" : "file2" }                                                                                            
{ "_id" : ObjectId("571e5a937e88d30b20b7857e"), "name" : "file22" } 
预期的是(字母顺序/自然顺序)

根据我的发现,还有其他排序方法,比如使用
aggregate
+
$project
$meta:“textScore”
,但到目前为止我还没有成功

更新: 此问题的一个应用:按名称对文件夹/文件进行排序

MongoDB没有提供一种开箱即用的方法,但您仍然有两种选择:

第一种是客户端处理,使用该方法对数组结果进行排序

db.mydata.find().toArray().sort((a, b) => { 
    var x = Number(a.name.match(/\d+/g)[0]); 
    var y = Number(b.name.match(/\d+/g)[0]);
    return x === y ? 0 :( x < y ? -1 : 1 );
})

MongoDB服务器版本2.6开始,您需要使用现在已弃用的API


从MongoDB服务器2.4版开始,您需要一种不同的方法

db.collection.find({}, { "name": 1 }).forEach(function(doc) {
    var fileId = Number(doc.name.match(/\d+/g)[0]); 
    db.collection.update(
        { "_id": doc._id },
        {"$set": { "fileId": fileId } } 
    );
})

执行任何此操作后,您的文档现在如下所示:

{ "_id" : ObjectId("571e5a787e88d30b20b7857c"), "name" : "file1", "fileId" : 1 }
{ "_id" : ObjectId("571e5a8c7e88d30b20b7857d"), "name" : "file11", "fileId" : 11 }
{ "_id" : ObjectId("571e5a977e88d30b20b7857f"), "name" : "file2", "fileId" : 2 }
{ "_id" : ObjectId("571e5a937e88d30b20b7857e"), "name" : "file22", "fileId" : 22 }

现在,您可以使用该方法轻松地对文档进行排序

这将产生以下结果:

{ "_id" : ObjectId("571e5a787e88d30b20b7857c"), "name" : "file1" }
{ "_id" : ObjectId("571e5a977e88d30b20b7857f"), "name" : "file2" }
{ "_id" : ObjectId("571e5a8c7e88d30b20b7857d"), "name" : "file11" }
{ "_id" : ObjectId("571e5a937e88d30b20b7857e"), "name" : "file22" }

它们是否都有共同的
文件
?我不确定
文件1
是如何按字母顺序排列的?在任何字典里都找不到
A
。我不会说你想做的是自然顺序。mongodb的自然顺序是指文档插入db的自然顺序:@BlazeSahlzen,我真的不想讨论正确的“术语”,已经有一篇关于这个()的文章了。我更改了问题的标题并添加了“natural sort”标记,因此我们应该关注问题的解决方案。如果所有人都同意MongoDB不提供此功能,并且必须使用JavaScript完成此功能,那么这就是解决方法。很高兴了解有关批量更新操作的更多信息。如果我们能够找出排序值的模式,那么引入额外字段是一条出路。但是,在这种情况下,该值可以是任何内容,如普通字符串、IP地址等。。。关于客户端方法,如果我们进行分页,这将是一个问题。除非您可以将所有数据返回到客户端(这可能会产生性能问题),否则这种方法将不会产生预期的结果。@6220119正如我所说的,规范化是绝对可行的,因为客户端操作将导致应用程序的性能下降。查找模式也应该是一个问题,因为“name”包含相同类型的值。例如,对于常规字符串,您可以先按字符串长度升序,然后按字母顺序对文档进行排序,这意味着您的额外字段将保留长度。但这绝对是你问题的解决办法。按长度排序,然后按字母顺序排序,不会得到正确的结果。看看有没有灵感。看起来这已经成为另一个问题了?如何使用mongoDB存储字符串值以执行排序操作?由于poster声明名称可以是任何内容,因此没有特定的模式,架构修改应将
名称
拆分为
基本
文件ID
。然后相应地排序:
排序({base:1,fileId:1})
db.collection.find({}, { "name": 1 }).forEach(function(doc) {
    var fileId = Number(doc.name.match(/\d+/g)[0]); 
    db.collection.update(
        { "_id": doc._id },
        {"$set": { "fileId": fileId } } 
    );
})
{ "_id" : ObjectId("571e5a787e88d30b20b7857c"), "name" : "file1", "fileId" : 1 }
{ "_id" : ObjectId("571e5a8c7e88d30b20b7857d"), "name" : "file11", "fileId" : 11 }
{ "_id" : ObjectId("571e5a977e88d30b20b7857f"), "name" : "file2", "fileId" : 2 }
{ "_id" : ObjectId("571e5a937e88d30b20b7857e"), "name" : "file22", "fileId" : 22 }
db.mydata.find({}, { "name": 1 } ).sort( { "fileId": 1 } )
{ "_id" : ObjectId("571e5a787e88d30b20b7857c"), "name" : "file1" }
{ "_id" : ObjectId("571e5a977e88d30b20b7857f"), "name" : "file2" }
{ "_id" : ObjectId("571e5a8c7e88d30b20b7857d"), "name" : "file11" }
{ "_id" : ObjectId("571e5a937e88d30b20b7857e"), "name" : "file22" }