Mongodb 动态mongo投影-使用文档中的字段确定投影的投影

Mongodb 动态mongo投影-使用文档中的字段确定投影的投影,mongodb,projection,Mongodb,Projection,假设我有一个这样的物体: {default: 'x', types: { x:1, y:2, z:3 } } var mapper = function() { var typeValue = this.types[this.default], typeKey = "types." + this.default; emit(this._id, { key : typeKey, val : typeValue } ); }; 是否可以只选

假设我有一个这样的物体:

{default: 'x',
 types: {
  x:1,
  y:2,
  z:3
 }
}
var mapper = function() {
    var typeValue = this.types[this.default],
        typeKey = "types." + this.default;

    emit(this._id, { key : typeKey, val : typeValue } );
};   

是否可以只选择types.x(即
{“types.x”:1}
)而事先不知道x是默认值?进行两次查询显然是可能的,而不是我想要的。

不幸的是,这还不是聚合框架的一部分。然而,据报道,这是目前“计划的,而不是预定的”。目前唯一的方法是使用map/reduce功能。如果你想继续使用它,就意味着要做以下事情:

var mapper = function() {
    var typeValue = this.types[this.default];
    emit(this._id, typeValue);
};
var reducer = "";

db.types.mapReduce(mapper, reducer, { out : "results" } );
> db.results.find();
{ "_id" : ObjectId("53d21a270dcfb83c7dba8da9"), "value" : 1 }
> db.results.find().pretty();
{
    "_id" : ObjectId("53d21a270dcfb83c7dba8da9"),
    "value" : {
        "key" : "types.x",
        "val" : 1
    }
}
  • 按_id映射每个文档并发出相应的键
  • 因为每个键只有一个值,所以不会调用reduce函数,但是您仍然需要初始化reduce函数使用的变量。可以使用空函数或空字符串
  • 运行map/reduce,将结果保存在您选择的集合中
  • mongo
    shell中,它看起来如下所示:

    var mapper = function() {
        var typeValue = this.types[this.default];
        emit(this._id, typeValue);
    };
    var reducer = "";
    
    db.types.mapReduce(mapper, reducer, { out : "results" } );
    
    > db.results.find();
    { "_id" : ObjectId("53d21a270dcfb83c7dba8da9"), "value" : 1 }
    
    > db.results.find().pretty();
    {
        "_id" : ObjectId("53d21a270dcfb83c7dba8da9"),
        "value" : {
            "key" : "types.x",
            "val" : 1
        }
    }
    
    如果随后查询结果集合,您将得到如下结果:

    var mapper = function() {
        var typeValue = this.types[this.default];
        emit(this._id, typeValue);
    };
    var reducer = "";
    
    db.types.mapReduce(mapper, reducer, { out : "results" } );
    
    > db.results.find();
    { "_id" : ObjectId("53d21a270dcfb83c7dba8da9"), "value" : 1 }
    
    > db.results.find().pretty();
    {
        "_id" : ObjectId("53d21a270dcfb83c7dba8da9"),
        "value" : {
            "key" : "types.x",
            "val" : 1
        }
    }
    
    如果您想知道默认值是什么,可以修改
    mapper
    函数,以便将键作为值返回。它看起来像这样:

    {default: 'x',
     types: {
      x:1,
      y:2,
      z:3
     }
    }
    
    var mapper = function() {
        var typeValue = this.types[this.default],
            typeKey = "types." + this.default;
    
        emit(this._id, { key : typeKey, val : typeValue } );
    };   
    
    运行时,将产生如下结果:

    var mapper = function() {
        var typeValue = this.types[this.default];
        emit(this._id, typeValue);
    };
    var reducer = "";
    
    db.types.mapReduce(mapper, reducer, { out : "results" } );
    
    > db.results.find();
    { "_id" : ObjectId("53d21a270dcfb83c7dba8da9"), "value" : 1 }
    
    > db.results.find().pretty();
    {
        "_id" : ObjectId("53d21a270dcfb83c7dba8da9"),
        "value" : {
            "key" : "types.x",
            "val" : 1
        }
    }
    

    请注意,这可能是一个比您想要的复杂得多的解决方案,但这是使用MongoDB而不向应用程序添加更多逻辑的唯一方法。

    谢谢您的回答。相比之下,我必须运行两个常规查询才能获得相同的效果,您知道这两个查询的性能是什么吗?还是运行一个选择所有类型的查询的性能?@BT,我不建议您使用Map/Reduce进行实时聚合。解释了其中的一些原因。如果不能更改模式,我认为最好的选择是运行两个常规查询。此外,您肯定应该推动实现我上面复制的JIRA票据中的功能。在社区的压力下,它可能会在未来版本的MongoDB中实现。希望早点儿,谢谢你提供的好消息。我会把我的评论添加到列表中这些白痴是谁投票来结束这样的问题?完全没有必要。嘿,白痴:当你投票结束某件事的时候,写一篇关于为什么的评论。如果你是对的,那么也许OP会在将来避免类似的问题。如果你错了,我们都会看到你的推理有多愚蠢。我认为这是公平的交易。每个文件都有自己的默认值吗?基于这一点,你想让这片区域被投影吗?所有可能的默认值都是预先知道的吗?想想看,如果您的模式不同(如果您将类型存储为带有{type:“x”,value:1}的数组),那么您可以使用聚合框架来实现这一点元素类型。嗯,有趣的想法。我很惊讶聚合框架不能处理关键字。每个文档都有自己的默认值,是的。默认值的可能值事先不知道。