考虑以下帖子集:
{
_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个评论的评论,我想只在“评论”数组下检索此评论。如果我这样做:
db.posts.find({}, {comments: { $elemMatch: {likes: 4}}})
......我得到了这个(这正是我想要的):
{
_id: 1,
comments: [
{
title: "CommentTitle2",
likes: 4
}
]
}
{
_id: 2,
comments: [
{
title: "CommentTitle4",
likes: 4
}
]
}
{
_id: 3
}
但是如何检索文档的其余字段而不必像下面那样声明它们中的每一个?这样,如果在帖子文档中添加了更多字段,我就不必更改查找查询
db.posts.find({}, {title: 1, category: 1, comments: { $elemMatch: {likes: 4}}})
由于
答案 0 :(得分:2)
- 编辑 -
很抱歉您误解了您的问题。我想你会发现我对这个问题的回答是你想要的。正如人们所评论的那样,你不能在查找中以这种方式进行投影,但你可以使用聚合来做到这一点:
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 }
)
为了得到你想要的东西,我们在find的投影部分使用位置$运算符。
请参阅文档以了解两种用法之间的区别:
http://docs.mongodb.org/manual/reference/operator/query/elemMatch/
http://docs.mongodb.org/manual/reference/operator/projection/elemMatch/
答案 1 :(得分:1)
这个问题已经很老了,但是我只是面临着同样的问题,我不想使用聚合管道,因为它是简单的查询,我只需要让所有字段将$ elemMatch应用于一个字段即可。
我正在使用Mongoose(这不是最初的问题,但是现在已经很频繁了),并且确切地知道了问题的意思(使用$ elemMatch时如何检索所有字段?),我这样做了:< / p>
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 });