Rob
Rob

Reputation: 1636

MongoDb group by date and paginate

I have many documents - each with a date field, each with different keys.... (well, they vary... such is the nature of mongo).

            {
                "_id" : ObjectId("5b5e5107b3218221345cb198"),
                "category" : "A",
                "type" : "toilet",
                "cleaned" : "yes",
                "date" : ISODate("2018-07-29T23:43:03.178+0000")
            }
            {
                "_id" : ObjectId("5b5e5119b3218221345cb199"),
                "category" : "B",
                "housed" : "no",
                "temp" : "44",
                "date" : ISODate("2018-08-10T10:22:22.774+0000")
            }

I am trying to group and paginate. I need to be able to group all the documents by date - ignoring the time. This way, I can display all documents belonging to a date.

When a viewer clicks next / previous, it shows the next / previous date etc... So I would need to also test to see if next and previous documents exist in order to build the pagination.

So far, my attempts have failed. My thoughts are - I need to find and group, but that didn't work. I read this blog post https://dzone.com/articles/aggregate-mongo-using-only and adapted it - but this also doesn't work... it returns only a date field (the datePartDay bit splits the date string up)

        db.getCollection("log").aggregate(
            {
                "$project":
                    {
                        _id: 0,
                        "datePartDay": {
                            "$concat": [
                                {"$substr": [{"$dayOfMonth": "$date"}, 0, 2]}, "-",
                                {"$substr": [{"$month": "$date"}, 0, 2]}, "-",
                                {"$substr": [{"$year": "$date"}, 0, 4]}
                            ]
                        }
                    }
            },
            {
                "$group":
                    {"date": "$datePartDay"}
            }
        )

My app is running on node - and I'm not using mongoose.

** EDIT **

@Anthony Winzlet

I couldn't get $slice to work - but I can set my match to only look within 3 days, thus limiting my results to only those which fall within 3 days.

db.collection.aggregate(
[
    { 
        "$match" : {
        // find the date range we want to look up
            "date" : {
                "$gte" : ISODate("2018-07-29T00:00:00.000+0000"),
                 "$lte" : ISODate("2018-09-10T00:00:00.000+0000")
            }
        }
    }, 
    { 
        "$group" : {
            "_id" : {
                "$dateToString" : {
                    "format" : "%Y-%m-%d", 
                    "date" : "$date"
                }
            }, 
            "data" : {
                "$push" : "$$ROOT"
            }
        }
    }
]
);

However, I'm not sure how performant this is?

Upvotes: 1

Views: 624

Answers (1)

Ashh
Ashh

Reputation: 46441

You can $group using $dateToString and then simply $push the $$ROOT elements to an array

db.collection.aggregate([
  { "$group": {
    "_id": {
      "$dateToString": {
        "format": "%Y-%m-%d",
        "date": "$date"
      }
    },
    "data": {
      "$push": "$$ROOT"
    }
  }}
])

Upvotes: 1

Related Questions