项目阶段操作符在投影数组中的行为

时间:2014-12-29 10:15:20

标签: mongodb aggregation-framework

我的问题与this密切相关,但不相似。

我的收藏中有一个示例文档:

db.t.insert({"a":1,"b":2});

我的目的是将combined类型array的字段与ab的{​​{1}}一起投影。([1,2])

我只是尝试与$project阶段聚合:

db.t.aggregate([
{$project:{"combined":[]}}
])

MongoDB会抛出错误:disallowed field type Array in object expression

这意味着无法将字段投影为数组。

但是当我使用$cond运算符来投影数组时,该字段会被投射。

db.t.aggregate([
{$project:{"combined":{$cond:[{$eq:[1,1]},["$a","$b"],"$a"]}}}
])

我得到了o / p:{"combined" : [ "$a", "$b" ] }

如果您注意到输出,ab的值将被视为文字,而不是字段路径。

任何人都可以向我解释这种行为吗?当我让条件失败时,

db.t.aggregate([
{$project:{"combined":{$cond:[{$eq:[1,2]},["$a","$b"],"$a"]}}}
])

我得到了$a被视为字段路径的预期输出,因为$a未被包含为数组元素。

1 个答案:

答案 0 :(得分:5)

我之前也遇到过这种情况,这很烦人,但实际上它正如文字["$a", "$b"]所记录的那样;关于不允许的字段类型的第一个错误是......不清楚为什么它会抱怨。但是,您必须遵循文档中展开的$project阶段语法的描述。我会尝试在这里做。从$project开始,

  

$ project阶段具有以下原型形式:

{ $project: { <specifications> } }

和规格可以是以下之一:

1. <field> : <1 or true or 0 or false>
2. <field> : <expression>

什么是表达?来自aggregation expressions

  

表达式可以包括字段路径和系统变量,文字,表达式对象和运算符表达式。

这些东西是什么?字段路径/系统变量应该是熟悉的:它是以$或$$为前缀的字符串文字。表达式对象的格式为

{ <field1>: <expression1>, ... }

虽然运算符表达式具有其中一种形式

{ <operator>: [ <argument1>, <argument2> ... ] }

{ <operator>: <argument> }

表示<operator>的一些枚举值列表。

什么是<argument>?文档不清楚,但根据我的经验,我认为它是任何表达式,取决于给定运算符的语法规则(检查问题中的运算符表达式"cond" : ...)。

数组仅适合作为参数列表和文字的容器。文字是文字 - 它们的内容不会针对字段路径或系统变量进行评估,这就是为什么$cond中的数组文字参数最终为值[ "$a", "$b" ]。参数数组中的表达式将被计算。

关于Array作为不允许的值类型的第一个错误对我来说有点奇怪,因为数组文字是一个有效的表达式,因此根据文档它可以是对象表达式中的值。我也没有看到将它解析为对象表达式的一部分时有任何歧义。看起来这只是他们为使解析更容易而制定的规则?您可以使用$literal“躲避”它以放入一个常量数组值:

db.collection.project([{ "$project" : { "combined" : { "$literal" : [1, 2] } } }])

我希望这有助于解释为什么事情会这样。我第一次尝试做[ "$a", "$b" ]这样的事情时感到很惊讶,但是它并没有像我预期的那样工作。如果有一个功能可以将字段路径打包到数组中,那就太好了。我$group在有序的值对上也找到了它的用途。

有一张JIRA票证SERVER-8141,要求$array运营商帮助处理此类案件。