如何在MongoDB聚合管道中隐藏单个子文档?

如何在MongoDB聚合管道中隐藏单个子文档?,mongodb,aggregation-framework,projection,Mongodb,Aggregation Framework,Projection,在find()查询中,可以在第二个参数中隐藏带有投影文档的字段: var cursor = collection.find(query, { '_id': false, 'unwanted': false }); 它将返回文档中的任何字段和子文档。这是有道理的 将此投影文档放入聚合管道时,为什么规则不同$project的工作原理不同: var cursor = collection.aggregate([ { $match : query

find()
查询中,可以在第二个参数中隐藏带有投影文档的字段:

var cursor = collection.find(query, {
    '_id': false,
    'unwanted': false
});
它将返回文档中的任何字段和子文档。这是有道理的

将此
投影
文档放入
聚合管道
时,为什么规则不同<代码>$project的工作原理不同:

var cursor = collection.aggregate([
    {
        $match      : query
    },
    {
        $project    : {
        '_id': false,
        'unwanted': false
        }
    }
]);
问题:

exception: The top-level _id field is the only field currently supported 
for exclusion
如何隐藏特定的子文档而不显式地包含所有需要的字段

编辑:除了一些索引字段外,文档中还有任意数量的字段,没有定义的架构。因此,我无法指定要包含的内容,因为我不知道文档中将包含哪些额外字段

想象一下,除了
\u id
不需要的
子文档之外,其他文档都带有随机场。我想去掉这两个


更新:

这个问题似乎不清楚,因为讨论的是逻辑,而不是问题。因此,让我举例说明一个低效的解决方案:

// node.js

var cursor = collection.aggregate([
    {
        $match     : query
    },
    // ...
]);

cursor.toArray(function(array){
    for (var i = 0; i < array.length; i++) {
        var document = array[i];
        delete document._id;
        delete document.unwanted;
    }
})
//node.js
var cursor=collection.aggregate([
{
$match:query
},
// ...
]);
cursor.toArray(函数(数组){
对于(var i=0;i
我不喜欢这样,因为将
光标
渲染到
数组
时会有开销,并且仅限于16MB大小的集合。此外,不必这样做正是投影文档的目的

因此,我的问题是,为什么我可以使用带有投影的
find()
,而不使用带有相同投影的
aggregate()
,来获得光标?逻辑在哪里?该功能显然在MongoDB适配器中,否则它也无法与
find()
一起使用。除了我刚才提到的解决方案外,还有哪些可能的解决方案或变通办法


我认为一种解决方案可以是使用
MongoDB 2.6
聚合函数
$redact
,但我不知道如何使用文档简单地删除一个静态子文档。此外,我不希望使用此选项,因为我们的大多数系统运行的是
MongoDB 2.4

,不幸的是,您无法在聚合管道中执行此操作,并且它在:

这是因为

如果指定包含文档中不存在的字段,
$project
将忽略该字段包含;i、 e.
$project
不会将字段添加到文档中

然后只需将生成的
$project
阶段添加到聚合管道中


但是如果您事先不知道模式,或者甚至不知道结果文档可能包含的所有字段,我认为您应该重新考虑设计


无论如何,另一个问题出现了,如果您不知道字段,您将如何进行聚合?我想这就是为什么MongoDB在
$project

中取消了字段排除功能的原因当我说我不想这样做时,我的意思是这不是一个选项,因为文档可以有任意数量的字段,并且没有定义的模式。我想删除带有元数据的某个字段,我需要一个解决方案。这对资源不好,但解决方案真的是将光标转换为数组并“暴力”遍历文档吗?因为我只有在使用管道查询所有文档后才知道字段,并且只有在知道所有字段后才能执行管道,所以这是一个第22条军规。我错了吗?那么你的意思是,只有在进行聚合查询后,你才能知道需要隐藏哪些字段?@Redsandro所以,如果我错了,请纠正我。你确切地知道你想隐藏哪些字段,但不是所有字段的列表,对吗?@Michael是的,那是不可能的Down Vote和close不应该被情绪化使用,如果没有留下建设性的评论就否决投票,那是很悲哀的。我认为这是由删除自己评论的人完成的。无论您是否可以想象一个这样的用例,为什么
find
aggregate
在同一个阶段似乎有一套不同的规则显然是一个很好而且很难回答的问题。
+-----------------------+---------------------------------------------------------+
|                Syntax | Description                                              |
+-----------------------+---------------------------------------------------------+
|  <field>: <1 or true> | Specify the inclusion of a field.                        |
|     _id: <0 or false> | Specify the suppression of the _id field.                |
| <field>: <expression> | Add a new field or reset the value of an existing field. |
+-----------------------+---------------------------------------------------------+
project_doc = {}
for field in fields
    if field not in to_be_hidden_fields:
        project_doc[field] = "$" + field
return {"$project": project_doc}