使用Go语言从MongoDB读取文档

huangapple go评论105阅读模式
英文:

Reading documents from MongoDB with GoLang

问题

我能够读写数据库中的文档,但我遇到了一些非常奇怪的行为。

如果搜索名字为"jack",我会得到所有的文档,而如果搜索名字为"Mike",我只会得到一个文档,但实际上有两个。

搜索方法:

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])
    }
}

输出结果:

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}

数据库中的内容如下:

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)
})

数据库连接:

// GetConnection - 获取到 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)
    }

    // 强制连接以验证连接字符串
    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
}

控制器:

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")
})

person 结构体:

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"`
}
英文:

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(&quot;looking for - &quot;, name)
	client, ctx, _ := getConnection()
	quickstart := client.Database(&quot;ginPlay&quot;)
	namesCollection := quickstart.Collection(&quot;names&quot;)
	var p []person
	nameObject, err := namesCollection.Find(ctx, bson.M {&quot;lastName&quot;: bson.D {
		{&quot;$gt&quot;, name},
	}})
	if err = nameObject.All(ctx, &amp;p); err != nil {
		panic(err)
	}

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

output

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

this is what is in the database

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

		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 := &quot;foo&quot;
	password := &quot;pass&quot;
	clusterEndpoint := &quot;cluster0.ml6z7m.mongodb.net/db?retryWrites=true&amp;w=majority&quot;

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

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

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

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

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

	fmt.Println(&quot;Connected to MongoDB!&quot;)
	return client, ctx, cancel

}

controller

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


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

答案1

得分: 1

findByFirstName()函数在给定的代码中通过lastName进行搜索,并对该字段执行大于($gt)操作,与给定的name进行比较:

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

你可能犯了一个错误,想要将"lastName"更改为"name"

只有Mike Smith被找到,因为Smith大于Mike(Mongo进行二进制字符串比较-参见这里)。同样的原因,即使对于Jack,输出也不正确;它还包括Mike Smith,因为SmithJill都大于Jack,但不大于Foo

英文:

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 {&quot;lastName&quot;: bson.D {
        {&quot;$gt&quot;, name},
    }})

You probably made a mistake and want to change &quot;lastName&quot; to &quot;name&quot;.

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.

huangapple
  • 本文由 发表于 2021年9月10日 22:59:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/69134199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定