Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to aggregate subdocuments #28

Closed
andrewryno opened this issue Aug 27, 2013 · 7 comments
Closed

Unable to aggregate subdocuments #28

andrewryno opened this issue Aug 27, 2013 · 7 comments

Comments

@andrewryno
Copy link
Contributor

I'm having a problem where I can't aggregate subdocuments. The problem is that my $columns argument has columns like subdocument.key. Mongo doesn't like that and spits out this error:

exception: the group aggregate field name 'metrics.clicks' cannot be used because $group's field names cannot contain '.'

Dump of the $group pipeline looks like this:

array(2) [
    '_id' => integer 0
    'metrics.clicks' => array(1) [
        '$sum' => string (15) "$metrics.clicks"
    ]
]

I'm not sure if this is even possible to fix without deviating too much from the Laravel query builder. Could possibly add a third optional parameter to rename columns, but I don't know if that would be wise.

Possibly introduce some set of characters to denote spaces, pass that to Mongo, and then split by those characters when Mongo comes back with the aggregates?

@rms2219
Copy link

rms2219 commented Aug 27, 2013

Can you use a "project" before the group to project $metric.clicks to something without a '.' in it? In my case, I have a "Order" document with an array of "Line" documents...I called $unwind on $lines and then projected "order.lines.cost" to 'cost', which I could then group:

MyModel::raw(function($collection){
               return $collection->aggregate(array(
                   array('$unwind' => '$lines'),
                   array('$project' => array(
                       'orderName' => '$orderName',
                       'cost' => array('$add' => '$lines.cost')
                   )),
                   array('$group' => array(
                       "_id" => '$orderName',
                       "lineCost" => array('$sum' => '$cost')
                   )),
               ));
            });

@andrewryno
Copy link
Contributor Author

I'm really trying to avoid having to use a raw query, simply because I just moved away from the default PHP driver for that reason. :P

So I was able to get this working. When you use the aggregate functions, it's completely unnecessary for the highest level key (in this case metrics.clicks) to be descriptive. So I did a "hacky" str_replace to fix it.

I can provide a patch/tests if anyone wants. It doesn't change the output at all. I get my aggregations perfectly. :)

@rms2219
Copy link

rms2219 commented Aug 27, 2013

I'd like to see how you did the aggregations without a raw query...I couldn't figure out what the format was for subdocuments, so I switched to raw.

@jenssegers
Copy link
Contributor

What would be the best solution; replace metrics.clicks with 'metrics_clicks', or just 'clicks'?

@andrewryno
Copy link
Contributor Author

Probably underscore, although it really doesn't matter since that key isn't used anywhere else, since the aggregate() function itself uses return $results[0][$columns[0]]; instead of a key string.

I'm working on a pull request right now.

@jenssegers
Copy link
Contributor

Sweet!

@andrewryno
Copy link
Contributor Author

Done in #29.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants