使用 mongoid 通过聚合计算数组大小

Use mongoid to count array size with aggregate

我正在尝试将聚合从 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}}
)

它会 return:

[{"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

它 return 是下一个错误:

Mongo::Error::OperationFailure: The argument to $size must be an Array, but was of type: EOO (17124)

我的问题是:如何让 Mongoid 理解 $tags 引用了正确的字段?或者代码中缺少什么?

谢谢

看起来有些数据字段中的数组并不一致。为此,您可以使用 $ifNull 在找到 none 的位置放置一个空数组,因此 return $size0:

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

当然,这会从选择中过滤掉那些文档,这可能是也可能不是预期的效果。