当前位置: 首页 > 知识库问答 >
问题:

在嵌套数组mongoose中仅返回第一个匹配键的聚合

楚志强
2023-03-14

我有一个如下的猫鼬模式

const PostSchema=mongoose.Schema({
    author: String,
    uid: String,
    comments:[
        {
            commentAuthor: String,
            uid: String,
            comment: String,
            userProfile: String,
            dateOfComment: String,
            replies: [{
                replyAuthor: String,
                authorProfile: String,
                reply: String,
                dateOfReply: String
            }]
        }
    ]
},{collection: 'SocialPost'});

我已经获取了所有具有给定id的特定用户发表评论的帖子,即所有那些评论数组中包含uid等于给定uid的对象的文档。例如,假设用户id为101,则查询结果可能如下所示:

[{
 author: 'gratis',
 uid: 101,
 ...,
 comments:[{
  commentAuthor: 'gratis',
  uid: 101,
  ...
},...]
},
...]

为了更好地理解一切,我想获取所有那些特定用户评论过的帖子,甚至回复过的帖子,以及只有该用户的评论和回复。

我所能做的就是:

SocialPost.aggregate([
{$match:{}},
{$unwind: "comments"},
{'$match': {"comments.uid": req.body.uid}}
])

此查询仅返回相应帖子的第一个匹配的评论项数组。我想要所有符合条件的物品。

请帮助我为我的问题设计正确的查询。

谢谢你!

共有2个答案

傅边浩
2023-03-14

虽然您的方法本身并不是不正确的,但是将注释作为对象数组写入PostsSchema会导致您现在遇到的问题,因为运行任何涉及来自多个帖子的注释的查询都会有点太冗长了。就我个人而言,我解决这个问题的方法是创建一个完全与帖子分开的CommentsSchema,然后通过Mongoose的填充()方法链接两者。新的模式可以是这样的:

const CommentsSchema = new mongoose.Schema({
  userId: {
    type: Schema.Types.ObjectId,
    required: true,
    ref: Users
  },
  postId: {
    type: Schema.Types.ObjectId,
    required: true,
    ref: Posts
  },
  parentCommentId: {
    type: Schema.Types.ObjectId,
    ref: Comments
  },
  comment: String,
  timestamps: true
});

这样,每个注释将通过userId、它引用的帖子(postId)以及,如果注释是对以下内容的回答,包括创建它的用户的信息(假设您有一个UsersSchema和一组用户)另一个,它回答的注释(父母的CommentId)。为了将帖子的评论提取为帖子集合中的额外字段,您可以在PostsSchema中创建一个虚拟字段:

PostsSchema.virtual('comments', {
  ref: Comments,
  localField: '_id',
  foreignField: 'postId'
});

然后,当您有一个post文档时,您可以像这样填充它的注释:post.populate(“comments”).execPopulate() 最后,提取用户编写的所有注释只需查询您的注释集合:

const userComments = await Comments.find({ userId: user._id });

我知道这些变化很大。但希望这种方法会更容易处理。

魏煜祺
2023-03-14

如果必须使用数组,并且要查找其中任何一个数组中都有值的文档,则可能需要使用$或以及$elemMatch

SocialPost.find({
    "$or": [
         { 'comments': { "$elemMatch" : { 'uid' : yourId} } },
         {'comments.replies':{"$elemMatch":{'uid':yourId}}}
     ]
},(err,result)=>{});

 类似资料:
  • 主要集合是零售商,其中包含用于商店的数组。每个商店都包含一系列优惠(您可以在此商店购买)。这提供了具有数组大小的数组。(见下面的例子) 现在我试图找到所有的优惠,这是在大小。 我尝试了这个查询: 我期待这样的输出: 但是,我的查询的输出还包含与XS、X和M不匹配的offer。 如何强制MongoDB只返回符合我查询的报价? 问候和感谢。

  • 我只需要对与查询匹配的嵌套对象上的值求和。看起来ElasticSearch确定与查询匹配的文档,然后对所有嵌套对象求和。从下面的大纲中,我想搜索嵌套对象。objtype=“A”并返回objvalue之和,仅用于匹配嵌套对象,我想得到值4。这可能吗?如果是,如何? 这是地图 这是我的文件 这是我的查询代码。

  • 我有两个模型;一个用于用户,另一个用于学习组。每个StudyGroup都有一个唯一的字段。用户模型有一个studyGroups字段,它是字符串的数组。一个用户可以加入多个学习组。 用户模型

  • 问题内容: 我有以下查询: 这将同时返回“匹配”对象(整个文档)和“ inner_hits”对象(嵌套在匹配内部)。 有没有办法让我只返回出现在“ inner_hits”结果中的匹配“查询”元素,而没有获取整个文档? 问题答案: 应该可以通过以下方式 在顶层 禁用source- field 来实现

  • 你好,我在Java中使用正则表达式时遇到了一个问题。 我试图解析这个: 使用此代码(模式匹配器) 我的问题是,我的regexp只返回模式的第一次出现,即使我有一段时间(matcher.find())。。

  • 问题内容: 我已经尝试过使用并且都没有返回文档。是在返回一个空数组被返回。在这两种情况下也是如此。 这是我的联系: 这是我的架构: 我的查询在这里: 我可以将内容上传到数据库,并通过RockMongo进行查看,但之后无法获取它们。这是我第一次使用MongoDB,因此我认为我只是缺少一些基础知识。向正确方向的任何推动都是很棒的! 问题答案: 建立模型所绑定的集合的名称的调用,默认值为复数的小写模型名