Meteor: как вернуть только одну запись для каждого значения из коллекции


В настоящее время я работаю над приложением Meteor, которое также имеет функцию чата.

Я хочу иметь список всех разговоров, которые показывают самое последнее сообщение в каждом разговоре. (Аналогично образцу основного обзора беседы )

Предположим, у меня есть коллекция сообщений с переменной conversationId. Новым сообщениям присваивается новый идентификатор conversationId, а всем ответам присваивается идентификатор conversationId первого сообщения.

Чтобы получить этот обзор беседы, мой вопрос заключается в том, как вернуть из моей коллекции только самую последнюю запись для каждого conversationId?

Вот где я застрял:

Template.tabsTwo.helpers({
  messages: function () {

    //to retrieve all messages from the logged in user, then retrieve the conversationIDs and drop duplicates
    var userMessages = Messages.find({senderId: Meteor.userId()}, {sort: {date_created: -1, subject: -1}});

    var userConversationIds = userMessages.map((function(a) {
      return a.conversationId;
    }));

    var uniqueConversationIDs = [];

    $.each(userConversationIds, function(i, el){
        if($.inArray(el, uniqueConversationIDs) === -1) uniqueConversationIDs.push(el);
    });

    return Messages.find({conversationId: {$in:uniqueConversationIDs}}, {sort: {date_created: -1}});
  }
});

Это все еще возвращает мне все сообщения. Я спрашиваю себя прямо сейчас, могу ли я изменить этот запрос, чтобы заставить его работать, или мне нужно подойти к этому по-другому (например, сделать цикл и a .findOne query)?

(я перепробовал много вещей и искал ответы в документах и так далее но есть проблемы с получением этого права. Любая помощь будет очень признательна.)

1 2

1 ответ:

Ваше первоначальное решение не работает, потому что вы получаете список идентификаторов разговоров, а затем отменяете всю проделанную работу, находя все сообщения для этих разговоров.

Один из подходов состоит в том, чтобы собрать все сообщения и сгруппировать их по разговору, а затем выбрать самое последнее из них в каждой группе. Вот одно из таких решений:
// Fetch this user's messages.
var userMessages = Messages
  .find({senderId: Meteor.userId()})
  .fetch();

var firstMessages = _.chain(userMessages)
  // Group all of the messages by conversation.
  .groupBy('conversationId')
  .map(function(messages) {
    // For each message in this conversation's messages, choose the
    // first one by date.
    return _.chain(messages)
      .sortBy(function(message) {return -message.created_at;})
      .first()
      .value();
  }).value();

return firstMessages;

firstMessages представляет собой массив документов сообщений, содержащих первое сообщение, добавленное текущим пользователем в каждом разговоре. он / она принимал в этом участие. Вы можете просто вернуть это значение из вашего помощника, но если вы хотите вернуть курсор, просто добавьте следующее:

var messageIds = _.pluck(userMessages, '_id');
return Messages.find({_id: {$in: messageIds}});