Go filter mongoDB by date range

Issue

I am trying to write a query using Golang where I would filter actions that where created today for a specific profileId and would give me the count. The problem is I do not know how to write a filter that would filter out items from a specific time range. And I can’t seem to find a proper solution where Golang and MongoDB was used.

The timestamp field in the Action struct is the creation date that has to be used to filter out the actions that where created that day.

If anyone could help me and would put me on the right track I would greatly appreciate it. Thank you.

Here is my code:

type Action struct {
    ID        primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
    ProfileID primitive.ObjectID `json:"profileID,omitempty" bson:"profileID,omitempty"`
    Timestamp time.Time          `json:"timestamp,omitempty" bson:"timestamp,omitempty"`
    TypeID    int                `json:"type" bson:"type"`
}

func MatchActionAmount(profileId primitive.ObjectID) (int64, error) {
    filter := bson.M{"profileID": profileId}
    count, err := getActionCountByFilter(filter)
    if err != nil {
        log.Error("Could not get action count, error: ", err)
        return 0, err
    }
    return count, nil
}

func getActionCountByFilter(filter primitive.M) (int64, error) {
    ctx, _ := db.GetTimeoutContext()
    return getActionCollection().CountDocuments(ctx, filter)
}

func getActionCollection() *mongo.Collection {
    return db.GetMongoCollection("action")
}

Solution

If the timestamp is always the creation date (it can’t be a future timestamp), you don’t really need a range (between) filter, you only need records where the creation timestamp is greater than today, 0 AM.

This is how it could look like:

now := time.Now()
year, month, day := now.Date()
today := time.Date(year, month, day, 0, 0, 0, 0, now.Location())
filter := bson.M{
    "profileID": profileId,
    "timestamp": bson.M{
        "$gte": today,
    },
}

(Note: if you want days interpreted in UTC, use now.UTC().Date() and time.UTC for the location.)

If you would want to write a range query where you need to restrict timestamp between 2 timestamps, this is how it could look like (this one restricts timestamps between today 0AM and tomorrow 0AM–so basically all day today):

filter := bson.M{
    "profileID": profileId,
    "timestamp": bson.M{
        "$gte": today,
        "$lt":  today.AddDate(0, 0, 1),
    },
}

Answered By – icza

Answer Checked By – Senaida (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.