Search code examples
mongodbgogo-gin

Reading documents from MongoDB with GoLang


I am able to read and write documents to database but I am experiencing some very strange behavior.

If search for the name "jack" I get every document and Mike I get just one document but they're two.

search method

func findByFirstName(name string)  {
    fmt.Println("looking for - ", name)
    client, ctx, _ := getConnection()
    quickstart := client.Database("ginPlay")
    namesCollection := quickstart.Collection("names")
    var p []person
    nameObject, err := namesCollection.Find(ctx, bson.M {"lastName": bson.D {
        {"$gt", name},
    }})
    if err = nameObject.All(ctx, &p); err != nil {
        panic(err)
    }

    for i := 0; i < len(p); i++ {
        fmt.Println(p[i])
    }
    
}

output

looking for -  Jack
Connected to MongoDB!
{ObjectID("613b706bf47bc212c3928870") Mike Smith 25 Netflix}
{ObjectID("613b706cf47bc212c3928872") Jack Jill 36 Surfing}
{ObjectID("613b706ef47bc212c3928874") Jack Jill 25 Hiking}
{ObjectID("613b706ff47bc212c3928876") Jack Jill 30 Snowboarding}
looking for -  Mike
Connected to MongoDB!
{ObjectID("613b706bf47bc212c3928870") Mike Smith 25 Netflix}

this is what is in the database

r.GET("/addPerson", func(c *gin.Context) {
        c.String(http.StatusOK, "Hello World!")
        p1 := person{Name: "Mike", LastName: "Foo", Age: 36, Hobbies: "Development"}
        p2 := person{Name: "Mike", LastName: "Smith", Age: 25, Hobbies: "Netflix"}
        p3 := person{Name: "Jack", LastName: "Jill", Age: 36, Hobbies: "Surfing"}
        p4 := person{Name: "Jack", LastName: "Jill", Age: 25, Hobbies: "Hiking"}
        p5 := person{Name: "Jack", LastName: "Jill", Age: 30, Hobbies: "Snowboarding"}

        writePerson(p1)
        writePerson(p2)
            writePerson(p3)
            writePerson(p4)
            writePerson(p5)
        })

database connection

// GetConnection - Retrieves a client to the DocumentDB
func getConnection() (*mongo.Client, context.Context, context.CancelFunc) {
    username := "foo"
    password := "pass"
    clusterEndpoint := "cluster0.ml6z7m.mongodb.net/db?retryWrites=true&w=majority"

    connectionURI := fmt.Sprintf(connectionStringTemplate, username, password, clusterEndpoint)

    client, err := mongo.NewClient(options.Client().ApplyURI(connectionURI))
    if err != nil {
        log.Printf("Failed to create client: %v", err)
    }

    ctx, cancel := context.WithTimeout(context.Background(), connectTimeout * time.Second)

    err = client.Connect(ctx)
    if err != nil {
        log.Printf("Failed to connect to cluster: %v", err)
    }

    // Force a connection to verify our connection string
    err = client.Ping(ctx, nil)
    if err != nil {
        log.Printf("Failed to ping cluster: %v", err)
    }

    fmt.Println("Connected to MongoDB!")
    return client, ctx, cancel

}

controller

r.GET("/mike", func(c *gin.Context) {
    c.String(http.StatusOK, "Mike")
    findByFirstName("Mike")
})
r.GET("/jack", func(c *gin.Context) {
    c.String(http.StatusOK, "Jack")
    findByFirstName("Jack")
})


type person struct {
    ID     primitive.ObjectID `bson:"_id,omitempty"`
    Name string `bson:"name,omitempty"`
    LastName string `bson:"lastName,omitempty"`
    Age int `bson:"age,omitempty"`
    Hobbies string `bson:"hobbies,omitempty"`
}

Solution

  • Function findByFirstName() is searching by lastName and performs greater-than ($gt) operation on that field and given name in posted code:

    nameObject, err := namesCollection.Find(ctx, bson.M {"lastName": bson.D {
            {"$gt", name},
        }})
    

    You probably made a mistake and want to change "lastName" to "name".

    Only Mike Smith is found because Smith > Mike (Mongo does binary string comparison - see here). Also, even for Jack output is not correct for the very same reason; it includes also Mike Smith as both Smith and Jill are > than Jack but not Foo.