Javascript 在MongoDB中按字母顺序对文档进行排序(也称为自然排序顺序,人类排序)
我想了解如何使用MongoDB实现这一点 我有名称为“file1”、“file2”、“file22”、“file11”的文档(名称可以是任何形式,没有特定的模式) 我运行查询以按名称对所有文档进行排序,结果与预期不符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});
> 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" }