可能? $添加数组的值与对象总值进行比较

mongodb native for node.js(驱动程序版本是2.2.4和MongoDB shell版本:3.2.9)

我的collections有这样的对象:

{x:[{v:0.002},{v:0.00002}],t:0.00202} //<this one has the full total in its values {x:[{v:0.002},{v:0.002}],t:0.00202} {x:[{v:0.002},{v:0.002}],t:0.3} 

(这里显示没有他们的对象id)

我不确定如何将所有xv加起来,只返回xv总和大于或等于对象t的对象

 aggregate({"t":{"$gte":{"$add":["xv"]}}}) 

返回每一个对象,我没有任何其他的想法阅读文档的语法的顺序。

mongodb甚至可以在查询中做到这一点?

有了MongoDB 3.2,你可以在这里采取几种方法。 你可以用$where操作符来查询:

 db.collection.find({ "$where": function() { return (this.x.reduce(function (a, b) { return a + bv; }, 0) > this.t); } }) 

示例输出

 /* 1 */ { "_id" : ObjectId("587107b3cbe62793a0f14e74"), "x" : [ { "v" : 0.002 }, { "v" : 0.002 } ], "t" : 0.00202 } 

但是请注意,由于使用$where操作符调用JavaScript引擎的查询操作来评估每个文档上的JavaScript代码并检查每个文档的条件,所以这肯定不是一个非常有效的解决scheme。

这是非常缓慢的,因为MongoDB在$whereexpression式和非$where查询语句可以使用索引之前评估非$where查询操作。

如果可以的话,build议与索引查询结合起来,以便查询速度更快。 但是,强烈build议您使用JavaScriptexpression式和$where操作符作为最后的手段,当您不能以任何其他方式构造数据或处理一小部分数据时。


一个更好的方法是使用聚合框架,你可以使用$unwind操作符来压扁数组x ,在$groupstream水线中计算xv的总和,然后使用$redactstream水线阶段过滤文档。 这允许您使用$cond操作符处理逻辑条件,并使用特殊操作$$KEEP将逻辑条件为true的文档“保留”,或者使用$$PRUNE删除条件为false的文档。

这个操作类似于使用$projectpipe道来select集合中的字段,并创build一个新的字段来保存来自逻辑条件查询的结果,然后进行后续的$match ,除了$redact使用更多的单一pipe道阶段高效。

 db.collection.aggregate([ { "$unwind": "$x" }, { "$group": { "_id": "$_id", "x": { "$push": "$x" }, "t": { "$first": "$t" }, "y": { "$sum": "$xv" } } }, { "$redact": { "$cond": [ { "$gt": [ "$y", "$t" ] }, "$$KEEP", "$$PRUNE" ] } } ]) 

示例输出

 /* 1 */ { "_id" : ObjectId("587107b3cbe62793a0f14e74"), "x" : [ { "v" : 0.002 }, { "v" : 0.002 } ], "t" : 0.00202, "y" : 0.004 } 

然而,尽pipe这个解决scheme比使用$where的以前的解决scheme更好,但要记住使用$unwind操作符也可以限制大数据集的性能,因为它产生文档的笛卡尔乘积,即每个文档的副本每个数组入口使用更多的内存(聚集pipe线上可能的内存上限占总内存的10%),因此在展平过程中需要时间来处理文档。

而且,这个解决scheme需要知道文档字段,因为这是在$grouppipe道中需要的,通过使用诸如$first$last的累加器来保留分组过程中的字段。 如果您的查询需要dynamic,这可能是一个巨大的限制。


为了最有效的解决scheme,我build议将你的MongoDB服务器$redact 3.4,并且使用$redactpipe道阶段和新的$reduce数组操作符以无缝的方式过滤文档。

$reduce用于通过对数组中的每个元素应用一个expression式并将它们合并为一个单独的值来计算数组中xv字段的总和。

然后,您可以使用$redactpipe道评估的expression式来获得所需的结果:

 db.collection.aggregate([ { "$redact": { "$cond": [ { "$gt": [ { "$reduce": { "input": "$x", "initialValue": 0, "in": { "$add": ["$$value", "$$this.v"] } } }, "$t" ] }, "$$KEEP", "$$PRUNE" ] } } ]) 

示例输出

 /* 1 */ { "_id" : ObjectId("587107b3cbe62793a0f14e74"), "x" : [ { "v" : 0.002 }, { "v" : 0.002 } ], "t" : 0.00202 }