遍历 mongoDB (mongoose) 数组时访问 "current element"

Get access to the "current element" when traversing a mongoDB (mongoose) array

我有一个用于“post 之类的社交媒体”(称为 PostModel)的猫鼬模型,它具有以下模式:

{
  caption: String,
  comments: [
    {
      comment: String,
      // basically an array to store all those who liked the comment
      likedBy: [...] // array of references to a different model
    },
    ... // more comment objects like this
  ]
}

我只是想知道查询 post 时每条评论获得的点赞数。这不应该像现在这样烦人和困难。我在这上面花了4个多小时。

到目前为止我尝试过的:

尝试 1:

PostModel.findById(postId, {
  "comments.likes": { $size: "$comment.likedBy" } // gives the number of comments instead of the number of likes on the comment
})

尝试 2:

PostModel.findById(postId, {
  "comments.likes": { $size: "$likedBy" } // gives "likedBy not defined" error
})

尝试 3:

PostModel.findById(postId, {
  "comments.likes": { $size: "$comments.$likedBy" } // gives "FieldPath field names may not start with '$'. Consider using $getField or $setField" error
})

尝试 4:

PostModel.findById(postId, {
  "comments.likes": { $size: "$comments.$.likedBy" } // gives "FieldPath field names may not start with '$'. Consider using $getField or $setField" error
})

我基本上想像数组遍历一样访问这个“forEach”中的“当前元素”。例如:

const a = [{likes: ["x", "y"]}, {likes: ["a", "b"]}, {likes: []}];
a.forEach((element, index) => {
  console.log(element.likes.length) // this is what I want but for mongoDB
})
// output: 2 2 0

我到处找了4个小时也没找到解决办法。任何能让我远离当前方向的东西都会有所帮助。

我不想为了获取嵌套的 likedBy 数组的长度而将整个评论数组加载到内存中。否则这甚至不是问题。

如果您想从所有 comments 中获得喜欢的总数,您可以使用 $reduce 运算符:

{
    $project: {
        likes: {
            $reduce: {
                input: "$comments",
                initialValue: 0,
                in: { $add: [ "$$value", { $size: "$$this.likedBy" } ] }
            }
        }
    }
}

Mongo Playground

或者,您可能需要 $map 通过点赞的数量来丰富每条评论:

{
    $project: {
        comments: {
            $map: {
                input: "$comments",
                in: {
                    $mergeObjects: [
                        "$$this",
                        { $numberOfLikes: { $size: "$$this.likedBy" } }
                    ]
                }
            }
        }
    }
}

Mongo Playground