我的问题与this密切相关,但不相似。
我的收藏中有一个示例文档:
db.t.insert({"a":1,"b":2});
我的目的是将combined
类型array
的字段与a
和b
的{{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" ] }
。
如果您注意到输出,a
和b
的值将被视为文字,而不是字段路径。
任何人都可以向我解释这种行为吗?当我让条件失败时,
db.t.aggregate([
{$project:{"combined":{$cond:[{$eq:[1,2]},["$a","$b"],"$a"]}}}
])
我得到了$a
被视为字段路径的预期输出,因为$a
未被包含为数组元素。
答案 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
运营商帮助处理此类案件。