如何在mongodb中维护排序属性的顺序?

时间:2017-01-25 11:33:36

标签: javascript node.js mongodb sorting mongoose

根据question的答案,不保证对象的属性顺序。那么当我们将多个排序字段作为对象传递时,sort函数如何在MongoDB中完美地工作?

db.users.find({}).sort({firstName: 1, age:-1}).exec(callback);

mongodb如何知道它首先必须按firstName排序然后按年龄排序?这是错误的假设吗?

2 个答案:

答案 0 :(得分:10)

这是一个有趣的问题。

它适用于大多数ECMAScript实现实际上执行保留密钥顺序(例如,Node使用的V8)。但是,官方Node MongoDB driver并不鼓励使用它,而是提供两种不同的符号:

  

可以使用带有数组的选项参数sort来进行排序   排序首选项

{   "sort": [['field1','asc'], ['field2','desc']] }
     

使用单个升序字段,可以使用字段名称替换数组。

{   "sort": "name" }

Mongoose文档没有提到任何关于密钥顺序的信息(至少不是我所知道的)。但它也提供two different approaches to sorting

// sort by "field" ascending and "test" descending
query.sort({ field: 'asc', test: -1 });

// equivalent
query.sort('field -test');

事实上,似乎Mongoose排序功能基于错误(但目前有效)的假设。在使用多个键进行排序时,最好使用字符串表示法。 直接使用MongoDB时(例如在MongoDB shell中)使用对象表示法排序可正常工作,因为它不使用纯JSON而是使用extended JSON

另请参阅此相关问题:How can you specify the order of properties in a javascript object for a MongoDB index in node.js?

还有一个Mongoose issue

  是的,对于猫鼬和mongodb来说,这是一个不幸的困境   驱动程序。 ECMAScript说密钥没有订购,但它们是   实际上是在V8中订购的(数字键除外,这是一个讨厌的边缘   案例),可能会继续在V8中订购   可预见的未来。 您可以使用[['field1','asc']]语法或   特定于猫鼬的'field1 -field2'语法或ES2015 Map类   (如果你担心的话,它保证了钥匙的插入顺序)   关键订单。

因此,在使用Mongoose时,请使用字符串表示法或新添加的ES2015 Maps支持,这些支持保证按插入顺序排序。

答案 1 :(得分:1)

在您的示例中,您使用MongoDB中的排序操作索引,如果您使用多个字段排序,则可以创建复合索引以支持对多个字段进行排序。正如您提供索引时所做的那样,查询计划程序从索引(您的示例的顺序:firstname,lastname)获取排序顺序,它将按您的订单排序。在另一个例子中,它是一个javascript对象。 Javascript不保证排序。