【问题标题】:How can I retrieve all the fields when using $elemMatch?使用 $elemMatch 时如何检索所有字段?
【发布时间】:2014-03-02 12:57:49
【问题描述】:

考虑以下帖子集合:

{
    _id: 1,
    title: "Title1",
    category: "Category1",
    comments: [
                {
                    title: "CommentTitle1",
                    likes: 3
                },
                {
                    title: "CommentTitle2",
                    likes: 4
                }

            ]
}
{
    _id: 2,
    title: "Title2",
    category: "Category2",
    comments: [
                {
                    title: "CommentTitle3",
                    likes: 1
                },
                {
                    title: "CommentTitle4",
                    likes: 4
                }

            ]

}
{
    _id: 3,
    title: "Title3",
    category: "Category2",
    comments: [
                {
                    title: "CommentTitle5",
                    likes: 1
                },
                {
                    title: "CommentTitle6",
                    likes: 3
                }
        ]
    }

我想检索所有帖子,如果一个帖子有 4 个赞的评论,我想仅在“cmets”数组下检索该评论。如果我这样做:

db.posts.find({}, {comments: { $elemMatch: {likes: 4}}})

...我明白了(这正是我想要的):

{
    _id: 1,
    comments: [
        {
            title: "CommentTitle2",
            likes: 4
        }
    ]
}
{
    _id: 2,
    comments: [
        {
            title: "CommentTitle4",
            likes: 4
        }
    ]
}
{
    _id: 3
} 

但是我怎样才能检索文档的其余字段而不必像下面这样声明每个字段?这样,如果在 post 文档中添加更多字段,我就不必更改查找查询

db.posts.find({}, {title: 1, category: 1, comments: { $elemMatch: {likes: 4}}})

谢谢

【问题讨论】:

    标签: mongodb mongoose mongodb-query


    【解决方案1】:

    --编辑--

    抱歉,您的问题被误读了。我想你会发现我对这个问题的回答就是你要找的。正如人们评论的那样,您不能在查找中以这种方式投影,但您可以使用聚合来这样做:

    https://stackoverflow.com/a/21687032/2313887

    其余的答案同样有用。所以我想我会把它留在这里

    使用投影时,您必须指定所有需要的字段,或者根本不指定任何字段。

    您在这里本质上是在问,一旦您选择更改文档的输出并限制一个字段的显示方式,那么我可以避免指定行为。底线是考虑查询参数的投影部分,就像 SQL SELECT 一样查找。它的行为在于 * 或全部是默认值,之后是字段列表,可能是字段格式的一些操作.唯一的区别是 _id 默认情况下始终存在,除非通过排除它而另行指定,即 { _id: 0 }

    或者,如果您想过滤您需要将$elemMatch 放入query 本身的集合。投影中这里的用法是明确限制返回的文档只包含数组中匹配的元素。

    更改您的查询:

    db.posts.find(
        { comments: { $elemMatch: {likes: 4}}},
        { title: 1, category: 1, "comments.likes.$": 1 }
    )
    

    为了得到你想要的,我们在查找的投影部分使用位置$ 运算符。

    两种用法的区别参见文档:

    http://docs.mongodb.org/manual/reference/operator/query/elemMatch/

    http://docs.mongodb.org/manual/reference/operator/projection/elemMatch/

    【讨论】:

    • 嗨,尼尔。感谢您的回答。我认为我的解释不清楚。我想检索所有帖子,以及那些有 4 个赞的评论,我只想在评论数组下检索该评论。所以我认为投影是必要的。
    • @rasco22862 已将声明清除为您想要的。
    • 再次感谢。有没有办法在不明确设置每个字段(标题:1,类别:1等)的情况下做到这一点?因此,如果我在 post 文档中添加另一个字段,我就不必修改查询。
    • 另外,我正在尝试检索集合中的每个文档,而不仅仅是那些有 4 个赞的评论。
    • 你不能在一个查询中做到这一点,我建议做两个查询,一个用于有 4 个喜欢 cmets 的文档,一个用于带有少于 4 个喜欢但没有 cmets 的 cmets 的帖子并加入记忆中。
    【解决方案2】:

    这个问题已经很老了,但我刚刚遇到了同样的问题,我不想使用聚合管道,因为它是简单的查询,我只需要让所有字段应用 $elemMatch 到一个字段。

    我正在使用 Mongoose(这不是最初的问题,但现在它非常频繁),并得到问题所说的确切内容(使用 $elemMatch 时如何检索所有字段?)我做了这个:

    const projection = {};
    Object.keys(Model.schema.paths).forEach(key => {
        projection[key] = 1;
    });
    projection.subfield = { $elemMatch: { _id: subfieldId } };
    
    Model.find({}, projection).then((result) => console.log({ result });

    【讨论】:

    • @greg-449:这似乎不是一个问题。他们遇到了类似的问题,他们正在提供解决方案。
    猜你喜欢
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多