MongoDB& PHP - 返回嵌套数组的计数

时间:2011-09-13 12:41:38

标签: mongodb mongodb-php

想象一下,我有一个包含以下文档的MonogDB集合:

{name: 'Some Name', components: {ARRAY OF ITEMS}}

如何返回组件中的名称和项目数? 我是否必须使用map / reduce?

我正在使用PHP的Mongo扩展。

编辑:PHP中的当前代码片段(正常工作)但我只想要计算组件

$fields = array(
    'name', 'components'
);
$cursor = $this->collection->find(array(), $fields);
$cursor->sort(array('created_ts' => -1));

if (empty($cursor) == true) {
    return array();
} else {
    return iterator_to_array($cursor);
}

谢谢, 吉姆

4 个答案:

答案 0 :(得分:1)

您可以使用map-reduce,也可以使用简单的group查询,如下所示。由于我假设你的名字属性是一个唯一的密钥,这应该可以工作,即使它不是你通常使用组函数的原因:

db.test.group({
 key: { name:true },
 reduce: function(obj,prev) {
  var count = 0;
  for(k in obj.components)
   count++;
  prev.count = count;
 },
 initial: { count: 0}
});

您提到您有一个组件数组,但您似乎将组件存储为对象{}而不是数组[]。这就是为什么我必须在reduce函数中添加循环来计算组件对象的所有属性。如果它实际上是一个数组,那么你可以简单地使用.length属性。

在PHP中,它看起来像这样(来自Manual):

$keys = array('name' => 1);
$initial = array('count' => 0);
$reduce =<<<JS
function(obj,prev) {
  var count = 0;
  for(k in obj.components)
   count++;
  prev.count = count;
 },
JS;

$m = new Mongo();
$db = $m->selectDB('Database');
$coll = $db->selectCollection('Collection');
$data = $coll->group($keys, $initial, $reduce);

最后,我强烈建议,如果您尝试定期访问组件的计数,则将计数存储为文档的附加属性,并在其发生更改时进行更新。如果您尝试编写基于此计数进行过滤的查询,那么您还可以在该组件属性上添加索引。

答案 1 :(得分:0)

吉姆 -

这是两个独立的行动;除非你想利用PHP的结果,否则你会得到类似的结果:

$m = new Mongo();
$db = $m->selectDB('yourDB');
$collection = $db->selectCollection('MyCollection');
$cursor = $collection->find(array(), array("name"=>1, "components"=>1));
foreach($cursor as $key){
   echo($key['name'].' components: '.count($key['components']);
}

答案 2 :(得分:0)

您可以使用db.eval()并使用JavaScript编写计算。

答案 3 :(得分:0)

今天跑过这个,如果你使用带有聚合的新驱动程序,你可以在php中执行此操作(给定此模式)

   {name: 'Some Name', components: {ARRAY OF ITEMS}}

在PHP中:

   $collection = (new Client())->db->my_collection;
   $collection->aggregate([
       '$match' => ['name' => 'Some Name'],
       '$group' => [
             '_id' => null,
             'total'=> ['$sum' => "\$components"]
        ]
  ]);

PHP的诀窍是逃避$美元符号,这基本上是mongo文档在使用大小或总和时所说的

https://docs.mongodb.com/manual/reference/operator/aggregation/size/

https://docs.mongodb.com/manual/reference/operator/aggregation/sum/

我遇到的问题是mongo将字段放入"$field"并且PHP完全不喜欢它,因为它进行变量插值的方式。但是,一旦你逃离$,它就可以正常工作。

我认为对于这种特殊情况,你需要做类似的事情,但使用$project代替$group这样

   $collection = (new Client())->db->my_collection;
   $collection->aggregate([
       '$match' => ['name' => 'Some Name'],
       '$project' => [
            'name' => "\$name",
            'total'=> ['$sum' => "\$components"]
        ]
   ]);

这是一个古老的问题,但是因为没有回答,我会把它留在这里。