rimraf
rimraf

Reputation: 4126

Basic between dates queries $gte, $lte, etc

I'm having an issue with correct time formatting for my mongo query.

My questions are these:

Here's a complete example of what i've got going.

package main

import (
    // "fmt"
    "context"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

// Here's a JSON of the record as it is in the db
// { 
//  "_id" : ObjectId("5fa467af036d5f46914c423c"), 
//  "subscriptionRuleId" : "email@email", 
//  "eventDateTime" : ISODate("2020-11-05T20:59:27.096+0000"), 
//  "eventType" : "string-with-event-type", 
//  "passportAtlas" : "a long string", 
//  "_class" : "com.proj.info.model.dto.EventLog"
// }

type eventLog struct {
    SubscriptionRuleID string `json:"subscriptionRuleId,omitempty" bson:"subscriptionRuleId"`
    EventType string `json:"eventType" bson:"eventType"`
    EventDateTime time.Time `json:"eventDateTime" bson:"eventDateTime"`
    PassportAtlas string `json:"passportAtlas" bson:"passportAtlas`
}

func main() {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    client, err := mongo.Connect(ctx, clientOptions)

    if err != nil { log.Fatal(err) }

    err = client.Ping(ctx, nil)

    if err != nil { log.Fatal(err) }

    collection := client.Database("compose").Collection("eventLog")

    df := "2006-02-04"
    dateFrom, _ := time.Parse(df, "2020-11-20")
    dateTo, _ := time.Parse(df, "2020-11-21")

    // This does not seem to work. 
    // A log of the dates gives me the wrong dates

    log.Printf("\nFROM: %v\nTO: %v", dateFrom, dateTo)
    // OUTPUTS:
    // FROM: 2020-01-09 00:20:00 +0000 UTC
    // TO: 2020-01-10 00:21:00 +0000 UTC

    // Notice the dates are formatted wrong in the log.
    // Even though the dates are wrong, I would still match
    // Records with those wrong dates as i've got tens of thousands
    // over the last few years...
 
    query := bson.M{
        "eventDateTime": bson.M{
            "$gte": dateFrom,
            "$lt": dateTo,
        },
    }

    cur, err := collection.Find(ctx, query)

    if err != nil { log.Fatal(err) }

    defer cur.Close(context.Background())

    var eventLogs []eventLog

    for cur.Next(ctx) {
        var eventLog eventLog
        cur.Decode(&eventLog)
        eventLogs = append(eventLogs, eventLog)
    }

    if err := cur.Err(); err != nil { log.Fatal(err) }

    log.Printf("num records: %v", len(eventLogs))
}

Upvotes: 0

Views: 3351

Answers (2)

Muhammad Tariq
Muhammad Tariq

Reputation: 4674

Here is an example to show how we can use the Date Range to search documents in MongoDB using $gte and $lte

Here we are passing the CourseSearch as a parameter which will be populated from the frontend/UI.

The backend service will search data in Course collection.

type CourseSearch struct {
    Subject     string          `json:"subject,omitempty" bson:"subject,omitempty"`
    System      string          `json:"system,omitempty" bson:"system,omitempty"`
    FromDate    time.Time       `json:"from_date,omitempty" bson:"from_date"`
    ToDate      time.Time       `json:"to_date,omitempty" bson:"to_date"`
}
func SearchByDate(ctx context.Context, searchCriteria *CourseSearch) {

    fromDate := searchCriteria.FromDate
    toDate := searchCriteria.ToDate

    database := db.Conn.Database("Education")
    metadataCollection := database.Collection("Course")
    cursor, err := metadataCollection.Find(
        ctx,
        bson.D{
            {"subject", searchCriteria.Subject},
            {"system", searchCriteria.System},
            {"duration", bson.D{{"$gte", fromDate}, {"$lt", toDate}} },
        })

Upvotes: 0

Burak Serdar
Burak Serdar

Reputation: 51542

BSON is simply binary JSON. MongoDB queries are BSON document constructed using similar constructs, by using bson.M (which is a map[string]interface{}) for objects and slices of values for arrays. There is also a bson.D type that can be used to construct objects that preserve ordering of its fields.

API documentation for the bson package explains most of the things you should know. The most important thing is that Go types are mapped to their bson equivalents in the way you expect them. Bson dates map to time.Time.

Using your example:

query:=bson.M{"eventDateTime":bson.M{"$gte": fromDate, "$lt":toDate}}

where fromDate and toDate are time.Time values.

As another example, an $in query can be written as:

query:=bson.M{"field":bson.M{"$in":[]string{"value1","value2"}}}

Upvotes: 1

Related Questions