2015-04-02 2 views
5

Я работаю над системой сообщений, и мне нужно получить последнее сообщение от каждого пользователя, который отправил сообщение зарегистрированному пользователю. У меня есть эта структура в MongoDB:Mongoose - найти последнее сообщение от каждого пользователя

[{ 
    "_id": "551bd621bb5895e4109bc3ce", 
    "from": "admin", 
    "to": "user1", 
    "message": "message1", 
    "created": "2015-04-01T11:27:29.671Z" 
}, { 
    "_id": "551bd9acf26208ac1d9b831d", 
    "from": "user1", 
    "to": "admin", 
    "message": "message2", 
    "created": "2015-04-01T11:42:36.936Z" 
}, { 
    "_id": "551bdd6d849d53001dd8a64a", 
    "from": "user1", 
    "to": "user2", 
    "message": "message3", 
    "created": "2015-04-01T11:58:37.858Z" 
}, { 
    "_id": "551bdd99849d53001dd8a64b", 
    "from": "user2", 
    "to": "admin", 
    "__v": 0, 
    "message": "message4", 
    "created": "2015-04-01T11:59:21.005Z" 
}, { 
    "_id": "551bdda1849d53001dd8a64c", 
    "from": "user1", 
    "to": "admin", 
    "__v": 0, 
    "message": "message5", 
    "created": "2015-04-01T11:59:29.971Z" 
}] 

Мне нужно получить поля from, message и created от последнего сообщения каждого пользователя, отправившего сообщение для авторизованного пользователя. Я пробовал использовать разные, но он возвращает только одно поле. У меня есть это:

Message.find({ 
     to: req.user.username 
    }) 
    .select('message created') 
    .sort('-created') 
    .exec(function (err, messages) { 
     if (err) { 
      return res.status(400).send({ 
       message: getErrorMessage(err) 
      }); 
     } else { 
      res.json(messages) 
     } 
    }); 

но он возвращает всех пользователей, отправленных сообщений вошедшего пользователя, и мне нужно иметь только уникальных пользователей и их последнее сообщение. Есть ли способ, как это сделать с мангуста?

+0

возможно дубликат [ Mongodb Query: последняя запись по дате для каждого элемента] (http://stackoverflow.com/questions/29368141/mongodb-query-latest-record-by-date-for-each-item) – Dineshaws

ответ

7

Использование рамки агрегация, где ваши этапы трубопровода имеют $match, $sort, $group и $project выражения:

Message.aggregate(
    [ 
     // Matching pipeline, similar to find 
     { 
      "$match": { 
       "to": req.user.username 
      } 
     }, 
     // Sorting pipeline 
     { 
      "$sort": { 
       "created": -1 
      } 
     }, 
     // Grouping pipeline 
     { 
      "$group": { 
       "_id": "$from", 
       "message": { 
        "$first": "$message" 
       }, 
       "created": { 
        "$first": "$created" 
       } 
      } 
     }, 
     // Project pipeline, similar to select 
     { 
      "$project": { 
       "_id": 0, 
       "from": "$_id", 
       "message": 1, 
       "created": 1 
      } 
     } 
    ], 
    function(err, messages) { 
     // Result is an array of documents 
     if (err) { 
      return res.status(400).send({ 
       message: getErrorMessage(err) 
      }); 
     } else { 
      res.json(messages) 
     } 
    } 
); 

If req.user.username = "admin", с вашей коллекцией образцов, то результат:

{ 
    "result" : [ 
     { 
      "message" : "message4", 
      "created" : "2015-04-01T11:59:21.005Z", 
      "from" : "user2" 
     }, 
     { 
      "message" : "message5", 
      "created" : "2015-04-01T11:59:29.971Z", 
      "from" : "user1" 
     } 
    ], 
    "ok" : 1 
} 
+2

Удивительный, спасибо вы! –

Смежные вопросы