我试图将MongoDB shell中的聚合转换为使用Mongoid作为ODM的ruby代码。
我有一些像这样的文件(非常简单的例子):
{
"name": "Foo",
"tags": ["tag1", "tag2", "tagN"]
},
{
"name": "Bar",
"tags": ["tagA", "tag2"]
},
...
现在我想获取所有带有名称字段的文档以及每个文档的标签总数。
在MongoDB shell中,我可以使用聚合框架来实现它:
db.documents.aggregate(
{$project: {name: 1, tags_count: {$size: $tags}}
)
它将返回:
[{"name": "Foo", "tags_count": 3},
{"name": "Bar", "tags_count": 2}]
现在令人沮丧的是,我尝试使用Mongoid作为ODM在rails应用程序中实现相同的查询。
代码看起来像(使用rails控制台):
Document.collection.aggregate(
[
{'$project': {name: 1, tags_count: {'$size': '$tags'}}}
]
).to_a
然后它返回下一个错误:
Mongo :: Error :: OperationFailure:$ size的参数必须是一个数组,但类型为:EOO(17124)
我的问题是:如何让Mongoid明白$tags
是否参考了正确的字段?或者我在代码中遗漏了什么?
由于
答案 0 :(得分:2)
看起来有些数据在字段中一直没有数组。为此,您可以使用$ifNull
放置一个没有找到空数组的空数组,从而将$size
作为0
返回:
Document.collection.aggregate(
[
{'$project': {name: 1, tags_count: {'$size': { '$ifNull': [ '$tags', [] ] } } }}
]
).to_a
或者,您可以使用$exists
简单地跳过根本不存在字段的位置:
Document.collection.aggregate(
[
{'$match': { 'tags_count': { '$exists': true } } },
{'$project': {name: 1, tags_count: {'$size': '$tags'}}}
]
).to_a
但当然会从选择中过滤掉那些文件,这可能是也可能不是预期的效果。