如何订购mongodb $ lookup查询

时间:2018-09-08 11:18:12

标签: mongodb mongoose aggregation-framework

概述

一些设备正在收集数据并将其发送到Node / MongoDb端点。然后,用户将使用端点将所有这些数据放入json中。

模型

设备型号

const deviceSchema = new Schema({
    group: { type: Schema.Types.ObjectId, ref: 'Group' },
    deviceId: { type: String, unique: true },
    name: String,
    notes: String,
    pac: String,
    endCertificate: String,
    lat: Number,
    lng: Number
});

消息模型

const messageSchema = new Schema({
    deviceId: { type: String, required: true },
    raw: { type: String, required: true },
    receivedAt: { type: Date, default: Date.now() }
});
  

一台设备可以接收N条消息

要解决的问题

我想获取一个具有所有设备并具有包含以下内容的数组的json 属于该设备的所有消息。

[
   {
      "id":"5b86c323e95759603ad7ea54",
      "deviceId":"Device 01",
      "name":"Device bla",
      "notes":"...",
      "pac":"pac",
      "lat":-20.817396,
      "endCertificate":"cert",
      "lng":-27.031321,
      "messages":[
         {
            "id":"5b869a42e0b94041b5f21eed",
            "deviceId":"Device 01",
            "raw":"1111111",
            "receivedAt":"2018-08-29T13:04:43.641Z",
            "__v":0
         },
         {
            "id":"5b8c782fef4f8e98783f6f35",
            "deviceId":"Device 01",
            "raw":"2222222",
            "receivedAt":"2018-09-01T09:04:43.641Z",
            "__v":0
         },
         {
            "id":"5b8c7840ef4f8e98783f6f3e",
            "deviceId":"Device 01",
            "raw":"3333333",
            "receivedAt":"2018-09-02T09:04:43.641Z",
            "__v":0
         }
      ]
   },
   {
      "id":"5b8c28ec38c51813cd159bac",
      "deviceId":"Device 02",
      "name":"Device ...",
      "notes":"...",
      "lat":-27.812296,
      "lng":-27.073314,
      "__v":0,
      "messages":[
         {
            "id":"5b8c784cef4f8e98783f6f43",
            "deviceId":"Device 02",
            "raw":"1111111",
            "receivedAt":"2018-09-01T09:04:43.641Z",
            "__v":0
         }
      ]
   }
]

我的解决方案

要获取上面的json作为我的

const [results, itemCount] = await Promise.all([
    Device.aggregate([
        { $match: {} },
        {
            $lookup: {
                from: 'messageschemas',
                localField: 'deviceId',
                foreignField: 'deviceId',
                as: 'messages'
            }
        }
    ]).limit(req.query.limit).skip(req.skip)
        .exec(),
    Device.countDocuments(match)
    ]);
res.setHeader('X-Total-Count', itemCount);
res.send(results);

我的问题

如何将我从$ lookup收到的消息排序为message [] “ receivedAt”?

1 个答案:

答案 0 :(得分:0)

您需要$unwind messages数组,并可以将$sortreceivedAt字段一起应用,最后应用$group再次回滚到数组中。

Device.aggregate([
  { "$match": { }},
  { "$lookup": {
    "from": "messageschemas",
    "localField": "deviceId",
    "foreignField": "deviceId",
    "as": "messages"
  }},
  { "$unwind": "$messages" },
  { "$sort": { "messages.receivedAt": 1 }},
  { "$group": {
    "_id": "$_id",
    "messages": { "$push": "$messages" }
  }}
])

只需使用 3.6 $lookup语法

即可完成
Device.aggregate([
  { "$match": { }},
  { "$lookup": {
    "from": "messageschemas",
    "let": { "deviceId": "$deviceId" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": [ "$deviceId", "$$deviceId" ] } } },
      { "$sort": { "receivedAt": 1 }}
    ],
    "as": "messages"
  }}
])