简体   繁体   中英

Aggregate total and distinct count

I have a document to stored products, one receipt can have many products inside.

{"_id" : "59871e65fffe165420e0b324"
"receiptid" : "4BA/ZFY7AQ4HvfjUMTRTLg=="
"area_type" : 1
"report_type" : 3
"id_station" : 2317
"date" : "2017-08-05 00:00:00.000"
"time" : "1501979220"
"amount" : 10113958
"item" : 32
},
{"_id" : "59871e65fffe165420e0b324"
"receiptid" : "4BA/ZFY7AQ4HvfjUMTRTLg=="
"area_type" : 1
"report_type" : 3
"id_station" : 2317
"date" : "2017-08-05 00:00:00.000"
"time" : "1501979320"
"amount" : 4000000
"item" : 12
}

I want to count total amount and total receipt in one query:

$store = array(2317);
$cursor = $collection->aggregate([
    ['$match' => [ 'id_station' => ['$in' => $store ], 'date' => ['$gte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-08-01")*1000), '$lte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-08-01")*1000)]  ] ],              

    ['$group' => ['_id' => ["id_station" => '$id_station'], 
                 "amountclient"=> ['$sum' => '$amount']
                ]
    ],
    ['$group' => ['_id' => ["id_station" => '$id_station', "receiptid" => '$receiptid'], 
                 "receipt"=> ['$sum' => 1]
                ]
    ]
]);

But the query doesn't show anything, how can I correct it?
I want the result: {"store" => xxxx, "amount" => xxxx, "number of receipt" => xxx}

You want "distinct counts", which means you actually "compound" the grouping the other way around to what you are attempting:

$store = array(2317);
$cursor = $collection->aggregate([
    ['$match' => [ 
      'id_station' => ['$in' => $store ],
      'date' => [
        '$gte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-08-01")*1000),
        '$lte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-08-01")*1000)
      ]
    ]],              
    ['$group' => [
      '_id' => [ 'id_station' => '$id_station', 'receiptid' => '$receiptid' ],
      'amount' => [ '$sum' => '$amount' ]
    ]],
    [ '$group' => [
      '_id' => '$_id.id_station',
      'amount' => [ '$sum' => '$amount' ],
      'numReceipt' => [ '$sum' => 1 ]
    ]]
]);

The first $group "includes" the "receiptid" field in the grouping _id so that the results returns are the "distinct" combination of the two keys. This allows the accumulation of the "amount" over that combination, and means that only the "distinct" values of "receipt_id" per each "id_station" are actually returned.

The "second" $group cuts down the key to just the "distinct" "id_station" value alone. Note the notation as '$_id.id_station' since the value was placed in a "compound key" of the _id in the previous $group stage. This is how "pipelines" work, by only having the available "input" that was the "output" of the previous stage.

For the "amount" you can pass the value into $sum again, and where there were "multiple combinations of "id_station" and "receiptid" then this is now reduced down to the total for just the "id_station" key. So you are "totaling the totals" from the previous stage output by the new reduced grouping key.

As for the "number of receipts", since the first $group made those values "distinct" within each "id_station" , then the number is simply the [ '$sum' => 1 ] result.

Basically on the included data in the question where both the keys are shared in the documents, it would return the "total amount" and the count of 1 for the "receipts" since there is only one "distinct" value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM