Как заказать поисковый запрос mongodb $ - PullRequest
0 голосов
/ 08 сентября 2018

Обзор

Несколько устройств собирают данные и отправляют их в конечную точку 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, в messages [] 'ReceivedAt'?

1 Ответ

0 голосов
/ 08 сентября 2018

Вам необходимо $unwind массив messages и можно применять $sort с полем receivedAt и наконец $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"
  }}
])
...