使用"聚合"组合匹配查询的所有子文档的列表?

时间:2017-02-04 18:45:19

标签: php mongodb aggregation-framework

我试图使用PHP mongo库来"聚合"在这样的数据结构上:

{
    "_id": 100,
    "name": "Joe",
    "pets":[
        {
            "name": "Kill me",
            "animal": "Frog"
        },
        {
            "name": "Petrov",
            "animal": "Cat"
        },
        {
            "name": "Joe",
            "animal": "Frog"
        }
    ]
},
{
    "_id": 101,
    "name": "Jane",
    "pets":[
        {
            "name": "James",
            "animal": "Hedgehog"
        },
        {
            "name": "Franklin",
            "animal": "Frog"
        }
}

例如,如果我想获得动物是青蛙的所有子文档。请注意,我不希望所有匹配的"超级文档" (即带有_id的那些)。我想要一个看起来像这样的ARRAY:

    [
        {
            "name": "Kill me",
            "animal": "Frog"
        },
        {
            "name": "Joe",
            "animal": "Frog"
        },
        {
            "name": "Franklin",
            "animal": "Frog"
        }
     ]

我应该使用什么语法(在PHP中)来完成此任务?我知道它与聚合有关,但我找不到任何符合这种特定情况的东西。

1 个答案:

答案 0 :(得分:1)

您可以使用以下聚合。 $match查找数组Frog$unwind pets数组的文档。 $match文档有Frog,最后一步是将group匹配的文档放入数组。

<?php

    $mongo = new MongoDB\Driver\Manager("mongodb://localhost:27017");

    $pipeline = 
        [
            [   
                '$match' => 
                    [
                        'pets.animal' => 'Frog',
                    ],
            ],
            [   
                '$unwind' =>'$pets',
            ],
            [   
                '$match' => 
                    [
                        'pets.animal' => 'Frog',
                    ],
            ],
            [
                '$group' => 
                    [
                        '_id' => null,
                        'animals' => ['$push' => '$pets'],
                    ],
            ],
        ];

    $command = new \MongoDB\Driver\Command([
        'aggregate' => 'insert_collection_name', 
        'pipeline' => $pipeline
    ]);

    $cursor = $mongo->executeCommand('insert_db_name', $command);

    foreach($cursor as $key => $document) {
            //do something
    }

?>