仅返回嵌入文档列表中的某些字段

时间:2016-03-31 07:22:19

标签: javascript mongodb mapreduce mongodb-query

这是我的文件:

{
"_id" : "2",
"account" : "1234",
"positions" : { 
  "APPL" : { "quantity" : "13", "direction" : "long" }, 
  "GOOG" : { "quantity" : "24", "direction" : "long" }
 }
}

我想获得整个位置对象,但只有数量字段忽略方向字段。有可能吗?或者我应该考虑这个其他模式(对象数组):

{
"_id" : "2",
"account" : "1234",
"positions" : [ 
  { "name" : "APPL", "quantity" : "13", "direction" : "long" }, 
  { "name" : "GOOG", "quantity" : "24", "direction" : "long" }
 ]
}

非常感谢!

1 个答案:

答案 0 :(得分:1)

对于"数组"表单,您真正需要做的就是使用"dot notation"为数组成员指定字段:

db.collection.find({}, { "positions.quantity": 1, })

哪会回来:

{
  "_id" : "2",
  "positions" : [
    { "quantity" : "13" },
    { "quantity" : "24" }
  ]
}

或者对于多个字段,但不包括"direction",只需在投影中使用两者:

db.collection.find({},{ "positions.name": 1, "positions.quantity": 1 })

仍然返回命名字段:

{
  "_id" : "2",
  "positions" : [
    {
            "name" : "APPL",
            "quantity" : "13"
    },
    {
            "name" : "GOOG",
            "quantity" : "24"
    }
  ]
}

对于"命名键"您需要指定每个路径:

db.collection.find({},{ "positions.APPL.quantity": 1, "positions.GOOG.quantity": 1  })

当然会返回:

{
  "_id" : "2",
  "positions" : {
    "APPL" : {
      "quantity" : "13"
    },
    "GOOG" : {
      "quantity" : "24"
    }
  }
}

那种" nastiness"基本上是 ALL MongoDB操作,查询或投影或其他方式普遍存在。当你使用"命名键" "数据库"没有理智的选择,除了要求你命名路径"。当密钥的名称在集合中的文档之间可能不同时,这样做当然不是真正的实践练习。

从MongoDB的角度来看,遍历键只能在JavaScript评估中完成。由于JavaScript评估在启动和将数据从BSON转换为可行的JavaScript格式时需要翻译成本,更不用说评估编码表达式本身的实际成本,这不是一种理想的方法。

此外,来自"查询"透视这样的处理需要使用$where来评估这样一个表达式,你只想在每个"键"下查找事物。 "positions"数据。这是一个"坏"事情,因为这样的表达不可能使用"索引"优化查询搜索。只有一个"直接命名的路径"你真的可以使用甚至"创造"在这些条件下的指数。

来自"预测"透视,"命名键的使用"意味着通过类似的"遍历"概念,你实际上需要再次执行JavaScript处理。以及唯一机制,MongoDB可以使用JavaScript表达式来改变"输出文档是使用mapReduce所以再次这是"超级可怕"你将使用这种"聚合方法"只是在这种情况下文档操作:

db.collection.mapReduce(
    function() {
        var id = this._id;
        delete this._id;
        Object.keys(this.positions).forEach(function(el) {
            delete el.direction;
        });
        emit(id,this);
    },
    function() {},    // reducer never gets called when all are unique
    { "out": { "inline": 1 } }
)

即使你这样做以避免命名路径,mapReduce的输出也不能是"光标"。因此,这会限制您响应实际输出到"集合"的BSON文档的大小。代替。所以这远远不是"实用"你可以得到。

有很多原因"为什么"使用带有"公共路径的数组"比命名键"更好。这个结构也太广泛了,无法进入这里。您应该接受的一件事是"命名键是坏的,好的!" 并且只是向前推进一致的对象命名实际上非常有意义。