0

I have the following (working) MongoDB query to generate a list of the hashtag count.

db.twitter.aggregate([
    { 
        $group: { 
            _id: "$status.entities.hashtags.text", 
            hashtags: { 
                $addToSet : "$status.entities.hashtags.text" 
            }
        }
    },
    { $unwind : "$hashtags" }, 
    { $unwind : "$hashtags" },
    { $group : { _id : "$hashtags", count: { $sum : 1 } } },
    { $sort : { count : -1, _id : 1 } }
]);

Now I try to convert this query to PHP code (for laravel):

$cursor = DB::collection('twitter')->raw(function($collection)
{
    return $collection->aggregate(array(
        array(
            '$group' => array(
                '_id' => '$status.entities.hashtags.text', 
                'hashtags' => array(
                    '$addToSet' => '$status.entities.hashtags.text',
                ),
            ),
        ),
        array(
            '$unwind' => '$hashtags',
        ),
        array(
            '$unwind' => '$hashtags',
        ),
        array(
            '$group' => array(
                '_id' => '$hashtags', '
                count' => array(
                    '$sum => 1',
                ),
            ),
        ),
        array(
            '$sort' => array(
                'count' => '-1', 
                '_id' => '1',
            ),
        ),
    ));
});

dd($cursor);

What I can derive from the Laravel-MongoDB docs is that the raw query input works the same as in PHP mongodb.

The error returned is this:

MongoResultException (15951)

localhost:27017: exception: the group aggregate field 'count' must be defined as an expression inside an object

2 Answers 2

1

You solved this but I can tell you where you was wrong:

'$sum => 1',

Should be:

array('$sum' => 1)
Sign up to request clarification or add additional context in comments.

Comments

1

Rewrote the array and now it works:

$cursor = DB::collection('twitter')->raw(function($collection)
{
    return $collection->aggregate([
        [ 
            '$group' => [ 
                '_id' => '$status.entities.hashtags.text', 
                'hashtags' => [
                    '$addToSet' => '$status.entities.hashtags.text'
                ]
            ]
        ],
        [ '$unwind' => '$hashtags' ], 
        [ '$unwind' => '$hashtags' ],
        [ '$group' => [ '_id' => [ '$toLower' => '$hashtags' ], 'count' => [ '$sum' => 1 ] ] ],
        [ '$sort' => [ 'count' => -1, '_id' => 1 ] ]
    ]);
});

Just replaced the {} by [] and the : by => and that did the trick!

5 Comments

Of course this is how PHP should be written now, array is so last seasons so +1
@Sammaye First of all thanks!! Can I ask you a related question? How can I lowercase the check, I tried to add [ '$project' => [ 'status.entities.hashtags.text' => [ '$toLower' => '$status.entities.hashtags.text' ] ] ] but it results in this error can't convert from BSON type Array to String.
This is something that gets me about MongoDBs aggregation framework, MongoDB is flexible and lossly compared but their aggregation framework is not. You might be able to use unwind here if it doesn't break when the field is somtimes a string. However if it does I know of no truly easy way, I dont think you can do a conditional unwind currently
I just got it to work! I used this line instead [ '$group' => [ '_id' => [ '$toLower' => '$hashtags' ], 'count' => [ '$sum' => 1 ] ] ], it is after the unwinds and I think that did the trick!
Nice, gotta remember that one

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.