Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb select all fields group by one field and sort by another field

We have collection 'message' with following fields

_id |   messageId |  chainId | createOn

1   |       1     |    A     | 155
2   |       2     |    A     | 185
3   |       3     |    A     | 225
4   |       4     |    B     | 226
5   |       5     |    C     | 228
6   |       6     |    B     | 300

We want to select all fields of document with following criteria

  1. distict by field 'chainId'
  2. order(sort) by 'createdOn' in desc order

so, the expected result is

_id |   messageId |  chainId | createOn

3   |       3     |    A     | 225
5   |       5     |    C     | 228
6   |       6     |    B     | 300

We are using spring-data in our java application. I tried to go with different approaches, nothing helped me so far.
Is it possible to achieve above with single query?

like image 826
Ajhar Shaikh Avatar asked May 06 '14 12:05

Ajhar Shaikh


People also ask

How do I group multiple fields in MongoDB?

For the implementation of the phenomenon of groups according to multiple fields, we need to have some data in the database. We will create a database first. This is done by declaring the name of the database with the keyword “use.” For this implementation, we are using a database “demo.”

How do I sort an array in MongoDB aggregation?

To sort the whole array by value, or to sort by array elements that are not documents, identify the input array and specify 1 for an ascending sort or -1 for descending sort in the sortBy parameter.


1 Answers

What you want is something that can be achieved with the aggregation framework. The basic form of ( which is useful to others ) is:

db.collection.aggregate([

    // Group by the grouping key, but keep the valid values
    { "$group": {
        "_id": "$chainId",
        "docId": { "$first": "$_id" },
        "messageId": { "$first": "$messageId" },
        "createOn": { "$first": "$createdOn" }
    }},

    // Then sort
    { "$sort": { "createOn": -1 } }

])

So that "groups" on the distinct values of "messageId" while taking the $first boundary values for each of the other fields. Alternately if you want the largest then use $last instead, but for either smallest or largest by row it probably makes sense to $sort first, otherwise just use $min and $max if the whole row is not important.

See the MongoDB aggregate() documentation for more information on usage, as well as the driver JavaDocs and SpringData Mongo connector documentation for more usage of the aggregate method and possible helpers.

like image 54
Neil Lunn Avatar answered Oct 19 '22 23:10

Neil Lunn