php f3 framework use aggregation framework pipelin

2019-09-14 19:24发布

问题:

I want to sue aggregation framework pipeline with mongo mapper in the transaction table, the result should be something like this: Suppose I have 7000 transactions in a collection with status 1,2,3,4 (1=pending, 2=confirmed, 3=decline, 4=claimed)

Data Representation:

Pending Count | Confirmed Count | Decline Count | Claimed Count
 4000                 2000            1000          0

1. The issue is I'm not sure which field should be used for the key in the group.

  1. My code is returning me all records which match the criteria.

please have a look at my code:

$filters = array('dateCreated'=>array(
                            '$gte'=>'2015-01-01', 
                            '$lte'=>'2017-05-15'
                    ));

 $group = [
              'keys' =>['userId'=>1],
              'initial' => ['pendingCount'=>0, 'confirmedCount'=>0, 'declineCount'=>0, 'claimedCount'=>0],
              'reduce'=>'
                      function(obj, result){

                        switch(result.status){
                            case 1:
                                result.pendingCount++;
                                break;

                            case 2:
                                result.confirmedCount++;
                                break;                          

                            case 3:
                                result.declineCount++;
                                break;
                            case 4:
                                result.claimedCount++;
                                break;

                        }
                      }
                        ',
              'finalize'=>'function(result){}'
        ];

 $data =  $this->mapper->find($filter, ['group'=>$group]);
 echo "data<pre>";
 print_r($data);

Output:

Here you see it returning me more than one docments but I just want one record for all transaction, may be key userId should be replaced something 'null`

Array ( [0] => Array ( [_id] => MongoId Object ( [$id] => 591a8f5bb06b243d0262d0a1 )

        [userId] => 
        [pendingCount] => 0
        [confirmedCount] => 0
        [declineCount] => 0
        [claimedCount] =>0
    )

[1] => Array
    (
        [_id] => MongoId Object
            (
                [$id] => 591a8f5bb06b243d0262d0a2
            )

        [userId] => 
        [pendingCount] => 0
        [confirmedCount] => 0
        [declineCount] => 0
        [claimedCount] =>0
    )

[2] => Array
    (
        [_id] => MongoId Object
            (
                [$id] => 591a8f5bb06b243d0262d0a3
            )

        [userId] => 38730976
        [pendingCount] => 0
        [confirmedCount] => 0
        [declineCount] => 0
        [claimedCount] =>0
    )

[3] => Array
    (
        [_id] => MongoId Object
            (
                [$id] => 591a8f5bb06b243d0262d0a4
            )

        [userId] => 64920
        [pendingCount] => 0
        [confirmedCount] => 0
        [declineCount] => 0
        [claimedCount] =>0
    )

....

回答1:

You're grouping by userId so you get one row per userId. Just pass an empty keys array to aggregate data against all records. Also there's a typo in your reducing function: it should be obj.status:

$group = [
  'keys' =>[],
  'initial' => ['pendingCount'=>0, 'confirmedCount'=>0, 'declineCount'=>0],
  'reduce'=>'
    function(obj, result){
      switch(obj.status){
        // etc.
      }
    }
  ',
  'finalize'=>'function(result){}'
];