1

So here is a sample of a document in my mongodb collection:

{
    "_id" : ObjectId("561e0de61c9218b7bf9877c3"),
    "Date" : NumberLong(20151014),
    "Hour" : NumberLong(10),
    "ProductId" : ObjectId("5614ba9c2e131caa098b4567"),
    "ProductName" : "Test",
    "ProducerId" : ObjectId("5617802151f8adf4db329d52"),
    "ProducerName" : "Producer",
    "ProducerRate" : NumberLong(300),
    "ProducerMedium" : "Emailer",
    "TotalLead" : NumberLong(6),
    "VerifiedLead" : NumberLong(3),
    "UnverifiedLead" : NumberLong(2),
    "UnQualifiedLead" : NumberLong(1),
    "TotalEarning" : NumberLong(660),
    "Consumers" : [ 
        {
            "ConsumerId" : ObjectId("5617802151f8adf4db329d54"),
            "ConsumerName" : "Consumer1",
            "ConsumedRate" : NumberLong(120),
            "ConsumedLead" : NumberLong(3),
            "Earning" : NumberLong(360)
        }, 
        {
            "ConsumerId" : ObjectId("5617802151f8adf4db329d58"),
            "ConsumerName" : "Consumer2",
            "ConsumedRate" : NumberLong(100),
            "ConsumedLead" : NumberLong(3),
            "Earning" : NumberLong(300)
        }
    ]
}

Now i want to get the ConsumedLead grouped by ConsumerId and ProductId from the database in php.

what i have did so far to give me TotalLead and VerifiedLead grouped by product id but have no idea how to get consumerbased results for same:

$keyf = new MongoCode('function(doc) {      
                return {\'ProductId\': doc.ProductId,\'ProductName\': doc.ProductName};
        }');
       $initial = array('TotalLead'=>0,'VerifiedLead'=>0);

        $reduce = "function(obj, prev) {
        prev.TotalLead += obj.TotalLead;
        prev.VerifiedLead += obj.VerifiedLead;

        }";
        $result = $collection->group($keyf, $initial, $reduce);
         var_dump($result);

Any Help Please.

EDIT: expected result wpuld be :

{ [0]=> array(4) { ["ProductId"]=> object(MongoId)#8 (1) { ["$id"]=> string(24) "5614ba9c2e131caa098b4567" } ["ProductName"]=> string(4) "Test" ["ConsumerId"]=> object(MongoId)#8 (1) { ["$id"]=> string(24) "5617802151f8adf4db329d58" } ["ConsumedLead"]=> float(4) } }
0

1 Answer 1

1

The solution is to use the aggregation framework where the operation includes an $unwind operator initial pipeline stage as this will deconstruct the Consumers array field from the input documents and outputs a document for each element. Each output document replaces the array with an element value. This will then make it possible for the $sum group accumulator operator in the $group step to work and thus givies you the required ConsumedLead grouped by ConsumerId and ProductId:

db.collection.aggregate([
    {
        "$unwind": "$Consumers"
    },
    {
        "$group": {
            "_id": {
                "ProductId": "$ProductId",
                "ConsumerId": "$Consumers.ConsumerId"
            },
            "TotalConsumedLead": {
                "$sum": "$Consumers.ConsumedLead"
            }
        }
    }
])

Running this aggregation operation on the above sample will result:

/* 0 */
{
    "result" : [ 
        {
            "_id" : {
                "ProductId" : ObjectId("5614ba9c2e131caa098b4567"),
                "ConsumerId" : ObjectId("5617802151f8adf4db329d58")
            },
            "TotalConsumedLead" : NumberLong(3)
        }, 
        {
            "_id" : {
                "ProductId" : ObjectId("5614ba9c2e131caa098b4567"),
                "ConsumerId" : ObjectId("5617802151f8adf4db329d54")
            },
            "TotalConsumedLead" : NumberLong(3)
        }
    ],
    "ok" : 1
}

So your final working aggregation in PHP should be:

$pipeline = array(    
    array('$unwind' => '$Consumers'),
    array(
        '$group' => array(
            '_id' => array(
                'ProductId' => '$ProductId',
                'ConsumerId' => '$Consumers.ConsumerId',
            ),
            'TotalConsumedLead' => array(
                '$sum' => '$Consumers.ConsumedLead'
            ),
        )
    ),
);

$out = $collection->aggregate($pipeline ,$options);
Sign up to request clarification or add additional context in comments.

1 Comment

@Nero Awesome, glad that helped :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.