Mongoose 切片数组,在填充字段中

Posted

技术标签:

【中文标题】Mongoose 切片数组,在填充字段中【英文标题】:Mongoose slice array, in populated field 【发布时间】:2016-09-15 08:26:36 【问题描述】:

我有以下mongoose 架构:

主要的是userSchema,其中包含一组朋友, friendSchema。每个friendSchema 都是一个包含messageSchema 数组的对象。 messageSchema 是最深的对象,包含消息的正文。

var messageSchema = new mongoose.Schema(
    ...
    body: String
);

var conversationsSchema = new mongoose.Schema(
    ...
    messages: [messageSchema]
);

var friendSchema = new mongoose.Schema(
  user: 
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
  ,
  conversation: 
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Conversation',
  ,
,  _id : false );


var userSchema = new mongoose.Schema(
    ...
    friends: [friendSchema]
);

在检索特定用户的朋友时,我会填充其朋友的个人资料,如果存在对话,我也会填充对话。 如何切片 conversations.messages 数组,该数组位于 conversationobject 的总体中?我不想返回全部消息。

  var userId = req.userid;
  var populateQuery = [ path:'friends.user', 
                         select: queries.overviewConversationFields ,
                        path:'friends.conversation' ];

  User
  .find( _id: userId ,  friends: 1 )
  .populate(populateQuery)
  .exec(function(err, result)
    if (err)  next(err); 
    console.log(result);
  

EDIT(1):我试过了

  .slice('friends.conversation.messages', -3)

EDIT(2):我尝试填充查询

   path:'friends.conversation', options:  'friends.conversation.messages':  $slice: -2  

EDIT(3) :现在,我可以实现我想要的,在执行查询后对数组进行切片。这根本没有优化。

【问题讨论】:

限制数组的大小为?能不能说的具体点。 由于数组包含两个用户之间的整个对话,我希望能够仅检索最后 25 条消息,例如 :) ***.com/questions/28514790/… 检查那里的第一个答案。应该做的伎俩。干杯 我不这么认为。此验证选项用于插入目的。 【参考方案1】:

一个可行的解决方法。 我没有找到如何$slice 驻留在填充字段中的数组。

但是$slice 运算符可以完美地在任何 array 上工作,只要其父文档尚未被填充。

1)我决定更新conversationSchema,添加一个数组,其中包含对话中涉及的两个用户ID:

var conversationsSchema = new mongoose.Schema(
    users: [type: mongoose.Schema.Types.ObjectId],
    messages: [messageSchema]
);

2) 然后,我可以轻松找到我的用户参与的每个对话。 正如我所说,我可以正确地对 messages 数组进行切片,因为不需要填充任何内容。

Conversation.find( users: userId , 
                   'messages':  $slice: -1 , function(err, conversation) 
);

3) 最后我要做的就是分别查询所有朋友和对话,然后用一个简单的循环和_find 将所有内容放回原处。 这将或多或少完成与 Mongo population

相同的过程

使用async.parallel 来提高效率:

 async.parallel(
      friends: function(done)
        User
          .find( _id: userId ,  friends: 1 )
          .populate(populateQuery)
          .exec(function(err, result)
          if (err)  return done(err);
          done(null, result[0].friends);
        );
      ,
      conversations: function(done)
        Conversation.find( users: userId ,  'messages':  $slice: -1 , function(err, conversation) 
          if (err)  return done(err); 
          done(null, conversation)
        );
      , function(err, results) 
          if (err)  return next(err); 

          var friends = results.friends;
          var conversations = results.conversations;

          for (var i = 0; i < friends.length; i++) 
            if (friends[i].conversation) 
              friends[i].conversation = _.find(conversations, function(conv) 
                return conv._id.equals(new ObjectId(friends[i].conversation));
              );
            
          

      );
      // Friends contains now every conversation, with the last sent message.

【讨论】:

以上是关于Mongoose 切片数组,在填充字段中的主要内容,如果未能解决你的问题,请参考以下文章

如何填充 Mongoose 数组中的字段?

Mongoose:使用 _id 以外的字段填充路径

Mongo - 如果子文档数组中的对象具有值,则添加字段

猫鼬填充返回空数组

如何在 NodeJS 和 Mongoose 中填充需要引用用户名的帖子

通过mongo中的填充字段查询[重复]