如何在php中转换mongoDB查询?

时间:2016-09-26 07:31:42

标签: php mongodb mongodb-query

我遇到了将mongoDB查询转换为php

的问题

这是我的mongoDB查询

db.contact_facts.mapReduce(
         function() {
             var k = new Date(this.date);
     k.setHours(0);
             k.setMinutes(0);
             k.setSeconds(0);
             k.setMilliseconds(0);
             emit({idM:this.idMailing,
        fact:this.fact,
        year:k.getFullYear(),
        month:k.getMonth(),
        day:k.getDate()
    }, 1);
         }, 
         function (key, values) {
            return Array.sum(values);
         },
         {
     query: { date: { $gt: ISODate('2016-09-20') } },
    out: { reduce: "contact_fact_stats2"},
         }
 );

我遇到了将此行转换为php代码的问题

query: { date: { $gt: ISODate('2016-09-20') } },

这是在php中写的

$dm = $this->getContainer()->get('doctrine_mongodb')->getManager();
$qb = $dm->createQueryBuilder('AtayenMainBundle:ContactFact');
$qb->field('date')->equals("ISODate('2016-09-20T08:42:30.000Z')");
$qb->map('function() {
         var k = new Date(this.date);
       k.setHours(0);
             k.setMinutes(0);
             k.setSeconds(0);
             k.setMilliseconds(0);
        emit({idM:this.idMailing,fact:this.fact,date:this.date}, 1)}');

$qb->reduce('function(key, values) {
        return Array.sum(values);

    }');

$cursor = $qb->getQuery()->execute();

1 个答案:

答案 0 :(得分:0)

我相信使用聚合框架可以更有效地完成相同的查询。聚合框架的性能更好,因为它运行"内部" MongoDB在其C ++代码中比mapReduce更有效,mapReduce在捆绑的JS控制台中的V8 / spidermonkey(取决于您的版本)环境中运行。

考虑运行以下管道以获得所需的结果:

var pipeline = [
    { "$match": { "date": { "$gt": new Date("2016-09-20") } } },
    {
        "$project": {
            "fact": 1,
            "idMailing": 1,
            "formattedDate": { 
                "$dateToString": { "format": "%Y-%m-%d", "date": "$date" } 
            }
        }
    },
    {
        "$group": {
            "_id": {
                "fact": "$fact",
                "idM": "$idMailing",
                "formattedDate":  "$formattedDate"
            },
            "count": { "$sum": 1 }
        }
    }
]
db.contact_facts.aggregate(pipeline);

在doctrine mongo odm中你可以使用命令函数运行你的管道操作,如下所示:

$connection = $this->getContainer()->get('doctrine_mongodb')->getConnection();
$mongo = $connection->getMongo();
if (!$mongo) {
    $connection->connect();
    $mongo = $connection->getMongo();
}
$db = $mongo->selectDB('test_database');

// construct pipeline
$pipeline = array( 
    array("$match" => array("date" => array("$gt" => new MongoDate(strtotime("2016-09-20")) ) ) ),
    array( 
        "$project" => array(
            "formattedDate" => array( 
                "$dateToString" => array("format" => "%Y-%m-%d", "date"=>  "$date") 
            ),
            "fact" => 1,
            "idMailing" => 1
        )
    ),
    array(
        "$group" => array(
            "_id" => array(
                "fact" => "$fact",
                "idM" => "$idMailing",
                "formattedDate" => "$formattedDate"
            ),
            "count" => array( "$sum" => 1 )
        )
    )
);

// run the aggregate command
$aggregate_results = $db ->command(array( 
    "aggregate" => "contact_facts",
    "pipeline" => $pipeline
));

或创建聚合查询:

$expr = new \Solution\MongoAggregation\Pipeline\Operators\Expr;
$aq = $this->get('doctrine_mongodb.odm.default_aggregation_query')
        ->getCollection('AtayenMainBundle:ContactFact')->createAggregateQuery()
        ->group(['_id' => [
            'year' => $expr->year('$date'),
            'month' => $expr->month('$date'),
            'day' => $expr->day('$date'),
            'fact' => '$fact',
            'idMailing' => '$idMailing'
        ], 'count' => $expr->sum(1)]);

使用mapReduce操作,您可以将命令运行为:

$connection = $this->getContainer()->get('doctrine_mongodb')->getConnection();
$mongo = $connection->getMongo();
if (!$mongo) {
    $connection->connect();
    $mongo = $connection->getMongo();
}
$db = $mongo->selectDB('test_database');


// construct map and reduce functions
$map = new MongoCode("function() {
        var k = new Date(this.date);
        k.setHours(0);
        k.setMinutes(0);
        k.setSeconds(0);
        k.setMilliseconds(0);

        var obj = {
            idM: this.idMailing,
            fact: this.fact,
            year: k.getFullYear(),
            month: k.getMonth(),
            day: k.getDate()
        };
        emit(obj, 1);
    }");

$reduce = new MongoCode("function (key, values) {
    return Array.sum(values);
    }");

$mr = $db->command(array(
    "mapreduce" => "contact_facts", 
    "map" => $map,
    "reduce" => $reduce,
    "query" => array("date" => array("$gt" => new MongoDate(strtotime("2016-09-20")) ) ),
    "out" => array("merge" => "eventCounts")));

$results = $db->selectCollection($mr['result'])->find();

foreach ($results as $res) {
    echo "{$res['_id']} had {$res['value']} counts.\n";
}