41

users考虑集合中的 MongoDB 文档:

{ username : 'Alex', tags: ['C#', 'Java', 'C++'] }

有什么方法可以tags从服务器端获取数组的长度(不将标签传递给客户端)?

谢谢!

4

6 回答 6

31

如果用户名 Alex 是唯一的,您可以使用下一个代码:

db.test.insert({username:"Alex", tags: ['C#', 'Java', 'C++'] });
db.test.aggregate(
  {$match: {username : "Alex"}}, 
  {$unwind: "$tags"},
  {$project: {count:{$add:1}}},
  {$group: {_id: null, number: {$sum: "$count" }}}
);
{ "result" : [ { "_id" : null, "number" : 3 } ], "ok" : 1 }
于 2012-12-15T21:24:24.577 回答
19

现在 MongoDB(2.6 版本)支持 $size聚合操作。

从文档中:

{ <field>: { $size: <array> } }

您可以使用以下任一方法完成您想要的:

db.users.aggregate(
   [
      {
         $group: {
            _id: "$username",
            tags_count:  {$first: {$size: "$tags" }}
         }
      }
   ]
)

或者

db.users.aggregate(
   [
      {
         $project: {
            tags_count: {$size: "$tags"}
         }
      }
   ]
)
于 2014-04-08T14:38:16.043 回答
16

我认为使用$inc或按计划通过作业计算每次保存(作为单独的字段)的标签数量可能更有效。

您也可以使用 map/reduce(规范示例)来执行此操作,但这似乎不是您想要的。

我不确定是否可以完全按照您的要求进行操作,但是您可以使用$size查询与特定大小匹配的所有文档...

> db.collection.find({ tags : { $size: 3 }});

这会让你得到所有带有 3 个标签的文件......

于 2011-07-17T09:34:02.510 回答
10

xmm.dev 的答案可以简化:您可以直接在 $group 中求和,而不是使用中间字段“count”:

db.test.aggregate(
  {$match: {username : "Alex"}}, 
  {$unwind: "$tags"},
  {$group: {_id: null, number: {$sum: 1 }}}
) 
于 2014-02-07T11:17:04.730 回答
9

目前,唯一的方法似乎是使用db.eval,但这会锁定数据库以进行其他操作

最高效的方法是添加一个额外的字段来存储数组的长度并通过$inc$push操作来维护它。

于 2011-07-17T09:31:47.200 回答
0

我做了一个小工作,因为我需要查询数组大小并在它大于 0 时返回,但可以是 1-3 之间的任何值。

这是我的解决方案:

db.test.find($or : [{$field : { $exists : true, $size : 1}},
                    {$field : { $exists : true, $size : 2}},
                    {$field : { $exists : true, $size : 3}}, ])

当属性存在且大小为 1、2 或 3 时,这基本上会返回一个文档。如果用户正在寻找特定大小或范围内,则可以添加更多语句和增量。我知道它并不完美,但它确实有效并且相对较快。我的属性中只有 1-3 个尺寸,所以这个解决方案有效。

于 2014-11-06T16:01:43.520 回答