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



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

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

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

我的目的是投影一个名为 combined 的类型为 array 的字段,其中包含ab的值。([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没有作为数组元素封装。

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

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

{ $project: { <specifications> } }

规格可以是以下之一:

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

什么是表达式?从聚合表达式中,

表达式

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

这些东西中的每一个都是什么?字段路径/系统变量应该很熟悉:它是一个以 $ 或 $$ 为前缀的字符串文字。表达式对象具有以下形式

{ <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操作员帮助处理此类情况。

最新更新