简体   繁体   English

流星:如何为集合中的每个值仅返回一个条目

[英]Meteor: How to return only one entry for each value from collection

I am currently working on a Meteor application that also has a chat functionality. 我目前正在开发同时具有聊天功能的Meteor应用程序。

I want to have a list of all conversations that show the most recent message in each conversation. 我想要一个所有对话的列表,这些对话显示每个对话中的最新消息。 (Similar to Sample of a basic conversation overview ) (类似于基本对话概述的样本

Let's say I have a collection Messages with a variable conversationId . 比方说,我有一个可变的conversationId收集信息 New messages get assigned a new conversationId and any replies will get assigned the conversationId of the first message. 新消息将被分配一个新的sessionId,并且所有回复将被分配第一条消息的sessionId。

To achieve this conversation overview, my question is, how do I return from my collection only the most recent entry for each conversationId? 为了获得此对话概述,我的问题是,如何从集合中仅返回每个对话ID的最新条目?

This is where I am stuck: 这就是我被困的地方:

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}});
  }
});

This still gives me back all messages. 这仍然给了我所有信息。 I am asking myself right now if I can modify this query to make it work or if I need to approach this differently (eg do a loop and a .findOne query)? 我现在正在问自己是否可以修改此查询以使其起作用,或者是否需要以不同的方式进行处理(例如执行循环和.findOne查询)?

(I have tried many things and searched for answers in the docs and SO but have troubles getting this right. Any help would be greatly appreciated.) (我尝试了很多事情,并在文档和SO中寻找了答案,但在正确设置方面遇到了麻烦。任何帮助将不胜感激。)

Your initial solution doesn't work because you are getting a list of conversation ids, and then undoing all the work you did by finding all of the messages for those conversations. 最初的解决方案不起作用,因为您将获得一个对话ID列表,然后通过查找这些对话的所有消息来撤消所做的所有工作。

One approach, is to fetch all of the messages and group them by conversation, then select the most recent one in each grouping. 一种方法是获取所有消息并通过对话对其进行分组,然后在每个分组中选择最新的消息。 Here's one such solution: 这是一个这样的解决方案:

// 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 is an array of message documents containing the first message added by the current user in each conversation he/she participated in. You can just return that value from your helper, but If you'd prefer to return a cursor, just add the following: firstMessages是一组消息文档,其中包含当前用户在其参与的每个对话中添加的第一条消息。您可以从助手中返回该值,但是如果您希望返回游标,则只需添加以下内容:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM