Reputation: 3311
I am trying to return a collection of messages grouped by in_reply_to field, I have this code:
$result = $this->db->Message->aggregate(
array(
array(
'$project' => array('message' => 1, 'in_reply_to'=> 1, 'to_user' => 1, 'from_user' => 1)
),
array(
'$group' => array('_id' => '$in_reply_to'),
),
)
);
print_r($result);exit;
the result is:
Array (
[result] => Array (
[0] => Array (
[_id] => MongoId Object (
[$id] => 53a03d43b3f7e236470041a8
)
)
[1] => Array (
[_id] => MongoId Object (
[$id] => 53a03cbdb3f7e2e8350041bb
)
)
)
[ok] => 1
)
Ideally I'd like the entire Message object, but I did think that $project would be used to specify returns fields, even so, I dont get the fields I'm specifying.
Any help is greatly appreciated
Upvotes: 0
Views: 799
Reputation: 151112
In order to get all the messages in the thread you basically want to $push
$result = $this->db->Message->aggregate(
array(
array(
'$group' => array(
'_id' => '$in_reply_to',
'messages' => array(
'$push' => array(
'_id' => '$_id',
'message' => '$message',
'to_user' => '$to_user',
'from_user' =>'$from_user'
)
)
)
)
)
);
MongoDB 2.6 you have the $$ROOT
variable that shortens this:
$result = $this->db->Message->aggregate(
array(
array(
'$group' => array(
'_id' => '$in_reply_to',
'messages' => array(
'$push' => '$$ROOT'
)
)
)
)
);
So that puts all of the related messages inside the "messages" array tied to that key.
Just as side note, while you can do this you may as well just sort the results by your "in_reply_to" field and process them that way looking for changes in the value to indicate a new thread.
Sorting with a find would be the fastest way to process, even if it does not conveniently put everything right under the one key.
Upvotes: 2
Reputation: 12240
If you want to get additional fields beside _id
field, when using $group operator, you need to include them using some of the available accummulators like $first or $last. You can see the full list on the MongoDB $group documentation page.
The query will look like this:
$result = $this->db->Message->aggregate(
array(
array(
'$project' => array(
'message' => 1,
'in_reply_to'=> 1,
'to_user' => 1,
'from_user' => 1
)
),
array(
'$group' => array(
'_id' => '$in_reply_to',
'message' => array('$first' => '$message'),
'to_user' => ('$first' => '$to_user'),
'from_user' => ('$first' => '$from_user')
),
),
)
);
If the message
, to_user
and from_user
values are same in all documents using $last
instead of $first
$last
will produce the same results.
Upvotes: 0