如何在mongodb中引用子集合

时间:2012-08-20 18:59:33

标签: php mongodb

我希望按照目标分组,其数据格式低于格式。

[unique_id] => 649083802  
[objectives_compleeted_log_queue] => Array (  
)  
[objectives] => Array (      
        [37] => Array (  
            [is_completed] =>   
            [tasks] => Array (  
            [56] => Array (  
                [completed_count] => 0  
                [actions] => Array (  
                    [0] => 0  
                )  
            )  
        )  
    )  
    [96] => Array (  
        [is_completed] =>   
        [tasks] => Array (   
            [123] => Array (  
                [completed_count] => 0  
                [actions] => Array (  
                    [0] => 0  
                )  
            )  
        )  
    )  
    [97] => Array (  
        [is_completed] =>   
        [tasks] => Array (  
            [124] => Array (  
                [completed_count] => 0  
                [actions] => Array (  
                    [0] => 0  
                )  
            )  
        )  
    )

我需要在上面的例子中为每个目标(37,96,97 ......)分组unique_ids。对不起mongo db

非常新

1 个答案:

答案 0 :(得分:1)

根据经验,在文档中使用动态字段名称(例如objectives.37)会降低索引和查询的灵活性。对于初学者,您将无法利用multi-key indexes

尽管如此,我们可以使用map/reduce来聚合和计算现有架构中的不同ID。为了保持以下示例简洁,我将字段名称缩短为o,并将数据夹具中的无关数据缩短。

<?php

$m = new Mongo();
$db = $m->test;

$db->foo->drop();
$db->foo->insert(['o' => [36 => [], 63 => [], 64 => []]]);
$db->foo->insert(['o' => [12 => [], 36 => [], 97 => []]]);

$result = $db->command([
  'mapreduce' => 'foo',
  'map' => new MongoCode('
    function() {
      for (var key in this.o) emit(key, { count: 1 });
    }
  '),
  'reduce' => new MongoCode('
    function(key, values) {
      var r = { count: 0 };
      values.forEach(function(v) { r.count += v.count; });
      return r;
    }
  '),
  'out' => ['inline' => 1]
]);

echo json_encode($result, JSON_PRETTY_PRINT);

在这里,我们在整个集合中执行map函数,在我们处理的o个对象中发出每个唯一键。每次发射时,我们发出的初始值为{count: 1}。在映射之后,我们有大量的排放,包括密钥和{count: 1}对。然后调用我们的reduce方法来处理不同键的这些中间结果。 values参数中的每个对象都遵循相同的结构(即我们之前发出的相同值),并且我们应该返回相同结构的单个减少值。

此脚本将产生以下输出:

$ php mr.php 
{
    "results": [
        {
            "_id": "12",
            "value": {
                "count": 1
            }
        },
        {
            "_id": "36",
            "value": {
                "count": 2
            }
        },
        {
            "_id": "63",
            "value": {
                "count": 1
            }
        },
        {
            "_id": "64",
            "value": {
                "count": 1
            }
        },
        {
            "_id": "97",
            "value": {
                "count": 1
            }
        }
    ],
    "timeMillis": 17,
    "counts": {
        "input": 2,
        "emit": 6,
        "reduce": 1,
        "output": 5
    },
    "ok": 1
}

如果您重新设计了模式,以便objectives是嵌套对象的数组,我们可以利用MongoDB 2.2+中的aggregation framework来更轻松地计算相同的结果:< / p>

<?php

$m = new Mongo();
$db = $m->test;

$db->foo->drop();
$db->foo->insert(['o' => [['id' => 36], ['id' => 63], ['id' => 64]]]);
$db->foo->insert(['o' => [['id' => 12], ['id' => 36], ['id' => 97]]]);

$result = $db->command([
  'aggregate' => 'foo',
  'pipeline' => [
    ['$project' => ['o' => 1]],
    ['$unwind' => '$o'],
    ['$group' => ['_id' => '$o.id', 'count' => ['$sum' => 1]]],
  ],
]);

echo json_encode($result, JSON_PRETTY_PRINT);

在这里,我们使用聚合管道按顺序执行三个操作:

  • 投放扫描文档的o字段,类似于在查找查询中选择特定输出字段。
  • 展开我们遇到的每个o数组。将管道视为文档流,我们将有两个文档进入此步骤,每个文档在各自的o字段中有三个嵌套对象。展开将产生六个文档到下一步,每个o数组字段被数组的元素替换。
  • 此时对流中的所有文档进行分组,使用o.id字段作为分组标识符,并将总和作为每个元素的组值。对于每个分组元素,count值字段将增加一个。

此脚本生成输出:

$ php af.php 
{
    "result": [
        {
            "_id": 12,
            "count": 1
        },
        {
            "_id": 63,
            "count": 1
        },
        {
            "_id": 97,
            "count": 1
        },
        {
            "_id": 64,
            "count": 1
        },
        {
            "_id": 36,
            "count": 2
        }
    ],
    "ok": 1
}