用于组的 mongo 排序子文档

Posted

技术标签:

【中文标题】用于组的 mongo 排序子文档【英文标题】:mongo sort subdocument for group 【发布时间】:2018-01-07 10:46:13 【问题描述】:

我有一个会员收藏:


    "_id": ObjectId("597cace8e68903af813c4fe8"),
    "lastName": "Smith",
    "firstName": "Lloyd",
    "captain": ObjectId("597cace8e68903af813c4fe8")
 

    "_id": ObjectId("597cace8e68903af813c4fec"),
    "lastName": "Jones",
    "firstName": "Chris",
    "captain": ObjectId("597cace8e68903af813c4fe8")

captain 架构属性引用同一集合中的另一个文档。

我还有一个 orders 集合:


    "_id" : ObjectId("597cf7e165b6c3f5094080c9"),
    "orderTotal" : 99.86,
    "orderDate" : ISODate("2017-07-29T21:02:25.045Z"),
    "orderProducts" : [
            
                    "title" : "Beads",
                    "totalItemPrice" : 39.96
            ,
            
                    "title" : "Doubloons",
                    "totalItemPrice" : 59.9
            
    ],
    "memberId" : ObjectId("597cace8e68903af813c4fec")

memberId 是引用 members 集合的外键。

我正在准备一份报告,该报告如下所示,按船长分组,按升序(姓氏、名字)对船长的姓名进行排序。在队长组中,我希望成员以相同的方式排序:

MEMBER ORDERS

Captain: Lloyd Smith

Members:
  1. Chris Jones
    * Beads: $39.96
    * Doubloons: $59.90
    * Total: $99.86
  2. Lloyd Smith
    * No Orders
  etc..

Captain: George Taylor

Members:
  1. John Brown
    * Beads: $1.96
    * Doubloons: $9.00
    * Total: $10.96
  2. Chip Castle
    * Beads: $1.00
    * Doubloons: $9.00
    * Total: $10.00
  etc...

我有一个查询主要做我想要的,但它没有对成员名称进行排序

Member.aggregate(
  
    $lookup : 
      from : "orders",
      localField : "_id",
      foreignField : "memberId",
      as : "tmpOrders"
    
  ,
  
    $lookup : 
      from : "members",
      localField : "captain",
      foreignField : "_id",
      as : "tmpCaptains"
    
  ,
  
    $group: 
      _id: 
        captain: "$captain",
        captainFirstName: "$tmpCaptains.firstName",
        captainLastName: "$tmpCaptains.lastName"
      ,
      members: 
        $push: "$$ROOT"
      
    
  ,
  
    $project: 
      "_id.captainFirstName": 1,
      "_id.captainLastName": 1,
      "members.firstName": 1,
      "members.lastName": 1,
      "members.tmpOrders.orderDate": 1,
      "members.tmpOrders.orderTotal": 1,
      "members.tmpOrders.orderProducts.title": 1,
      "members.tmpOrders.orderProducts.totalItemPrice": 1
    ,
  ,
  
    $sort: 
      "_id.captainLastName": 1,
      "_id.captainFirstName": 1
    
  
)

除了我的排序问题,我愿意接受任何关于提高管道可读性和性能的建议。

【问题讨论】:

【参考方案1】:

我终于明白了!我需要$unwind 成员以$sort 他们,再加上一些其他步骤将数据放回所需的结构。

Member.aggregate([
  
      $lookup : 
        from : "orders",
        localField : "_id",
        foreignField : "kreweOfTucksId",
        as : "tmpOrders"
      
  ,
  
      $lookup : 
        from : "members",
        localField : "captain",
        foreignField : "_id",
        as : "tmpCaptain"
      
  ,
  
      $group: 
          _id: "$captain",
          captain: 
              $addToSet: 
                  firstName: "$tmpCaptain.firstName",
                  lastName: "$tmpCaptain.lastName"
              
          
          ,
          members: 
              $addToSet: 
                  _id: "$_id",
                  firstName: "$firstName",
                  lastName: "$lastName",
                  captain: "$captain",
                  orders: "$tmpOrders",

              
          
      
  ,
  
      $unwind: "$members"
  ,
  
      $sort: 
          "members.lastName": 1,
          "members.firstName": 1
      
  ,
  
      $group: 
          _id: "$captain",
          members: 
              $push: "$members"
          
      
  ,
  
      $sort: 
          "_id.lastName": 1,
          "_id.firstName": 1
      
  ,
  
      $project: 
        _id: 1,
        "members.firstName": 1,
        "members.lastName": 1,
        "members.orders.orderTotal": 1,
        "members.orders.orderDate": 1,
        "members.orders.orderProducts.title": 1,
        "members.orders.orderProducts.totalItemPrice": 1
      
  
])

鉴于生成此报告所需的步骤,我敢打赌有多种方法可以改进查询。如果有任何专家有改进建议,我将不胜感激。谢谢!

【讨论】:

以上是关于用于组的 mongo 排序子文档的主要内容,如果未能解决你的问题,请参考以下文章

Mongo - Java - 将所有文档排序字符串日期作为日期

将索引与 Mongo 的 $first 组运算符一起使用

为啥聚合+排序比mongo中的查找+排序更快?

为啥 Mongoose ORM 选择不使用常规的 mongo 语法进行查找、排序等?

markdown 线性分区用于按组的字母顺序排序,例如A-C

mongo 数组元素检索与排序