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

Bat*_*eam 1 mongodb aggregation-framework

我的问题与密切相关,但并不相似.

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

db.t.insert({"a":1,"b":2});
Run Code Online (Sandbox Code Playgroud)

我的目的是投影一个名为combinedtype 的字段array,其值为both abtogether.([1,2]).

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

db.t.aggregate([
{$project:{"combined":[]}}
])
Run Code Online (Sandbox Code Playgroud)

MongoDB抛出一个错误:disallowed field type Array in object expression.

这意味着不能将字段投影为数组.

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

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

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

如果您注意到输出,则将a和的值b视为文字,而不是字段路径.

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

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

我得到的预期输出$a被视为一个字段路径,因为$a它不是作为数组元素包含的.

wdb*_*ley 5

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

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

{ $project: { <specifications> } }
Run Code Online (Sandbox Code Playgroud)

和规格可以是以下之一:

1. <field> : <1 or true or 0 or false>
2. <field> : <expression>
Run Code Online (Sandbox Code Playgroud)

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

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

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

{ <field1>: <expression1>, ... }
Run Code Online (Sandbox Code Playgroud)

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

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

{ <operator>: <argument> }
Run Code Online (Sandbox Code Playgroud)

对于某些枚举的值列表<operator>.

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

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

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

db.collection.project([{ "$project" : { "combined" : { "$literal" : [1, 2] } } }])
Run Code Online (Sandbox Code Playgroud)

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

有一张JIRA票,SERVER-8141,要求$array操作员帮助处理这类案件.