【问题标题】:Can't merge results of query to create instant messaging inbox that shows latest messages无法合并查询结果以创建显示最新消息的即时消息收件箱
【发布时间】:2016-07-22 01:07:48
【问题描述】:

我正在开发基于线程/对话的即时消息功能(很像 Facebook、Hangouts 等)。我正在尝试让我的 API 提供经过身份验证的用户参与的对话列表,以及每个对话中的最新消息。

我已经坚持了几天了,我尝试了很多东西。我没有运气。如果我将我的消息作为对话的子文档,我可以这样做,但我所读到的内容是避免嵌套这样的无限数组。我很好奇我是否应该考虑重新设计架构,但首先我想看看是否有一个查询可以让我到达我需要的地方。

这是我的架构设置:

Conversation.js:

const mongoose = require('mongoose'),
      Schema = mongoose.Schema;

// Schema defines how chat messages will be stored in MongoDB
const ConversationSchema = new Schema({
  participants: [{ type: Schema.Types.ObjectId, ref: 'User'}],
});

module.exports = mongoose.model('Conversation', ConversationSchema);

Message.js:

const mongoose = require('mongoose'),
      Schema = mongoose.Schema;

const MessageSchema = new Schema({
  conversationId: {
    type: Schema.Types.ObjectId,
    required: true
  },
  body: {
    type: String,
    required: true
  },
  author: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  }
},
{
  timestamps: true // Saves createdAt and updatedAt as dates. createdAt will be our timestamp.
});

module.exports = mongoose.model('Message', MessageSchema);

这是迄今为止最接近我想要的结果的查询:

// Only return one message from each conversation to display as snippet
  Conversation.find({ participants: req.user._id })
   .select('_id')
   .exec(function(err, conversations) {
     if (err) {
       res.send({ error: err });
       return next(err);
     }

     let fullConversations = [];
     conversations.forEach(function(conversation) {
       Message.find({ 'conversationId': conversation._id })
        .sort('-createdAt')
        .limit(1)
        .exec(function(err, message) {
          fullConversations.concat(message);
          console.log(message);
       });
     });

    res.status(200).json({ conversations: fullConversations });
});
}

正确的信息是在控制台中登录。我尝试推送并连接到 fullConversations 数组,但它最终在响应中为空。我也不确定是否为与该 forEach 的每个单独对话运行单独的查询。这对我来说似乎效率不高,但我正在努力寻找另一种有效的方式。任何帮助或建议将不胜感激。谢谢!

【问题讨论】:

    标签: javascript node.js mongodb express mongoose


    【解决方案1】:

    我猜你正在更新 fullConversations 数组的函数正在异步运行,所以你在函数实际向其中添加任何数据之前返回 fullConversations 数组。

    let fullConversations = [];
    var notCompleted = conversations.length;
    conversations.forEach(function(conversation) {
      Message.find({ 'conversationId': conversation._id })
       .sort('-createdAt')
       .limit(1)
       .exec(function(err, message) {
         fullConversations.push(message);
         notCompleted--;
         console.log(message);
      });
    });
    
    while (notCompleted > 0) {
        // Wait
    }
    
    res.status(200).json({ conversations: fullConversations });
    

    【讨论】:

    【解决方案2】:

    根据 Mozilla 文档,concat 实际上返回一个新数组而不更新当前数组 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat)

    var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
    

    尝试改用push,因为它会改变当前数组(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

    fullConversations.push(message);
    

    编辑:NVM,你说你试过推。我认为这可能与异步的东西有关。我会尽快发布更好的答案。

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 2012-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多