MongoDB 在 Go 中相对于 JSON 和 BSON

MongoDB in Go in relation to JSON and BSON

我正在学习如何使用社区维护的 mgo 回购链接 here

我通过这个发现example that the way to query for some pieces of data seems to be done through BSON (The community maintained version of the BSON library is linked here):

type Person struct {
    Name      string
    Phone     string
}

c.Find(bson.M{"name": "Alice"}).All(&result)

这将给我名称为 Alice 的所有 Person

我还发现我不需要 BSON 来执行此查询。 Find() 采用任何接口:

c.Find(Person{
    Name: "Alice",
    Phone: "1234",
}).All(&result)

也可以,但只返回指定的确切查询。如果我像这样遗漏了一部分结构:

c.Find(Person{
    Name: "Alice",
}).All(&result)

result 将为空。


在我看来,避免BSON更直观、更简单。所以我的问题是:

  1. 我应该避免 BSON 导入吗?
  2. 我可以在不使用 BSON 或不指定整个接口的情况下查询所有匹配模式吗?
  3. 我应该像 json:"name" 那样同时指定 JSON 和 BSON 键还是 它们可以互换吗?
  1. Should I avoid the BSON import?

我认为没有理由这样做。 MongoDB(通过mgo)和BSON携手同行。是否导入 bson 并不重要,bson 仍将在后台使用(序列化/表示来回发送的数据)。

  1. Can I query for all matching patterns wtihout using BSON or specifying the entire interface?

可以,如果您在指定 "bson" 标签时使用 omitempty 选项,就像这样:

type Person struct {
    Name  string `bson:"name,omitempty"`
    Phone string `bson:"phone,omitempty"`
}

现在,如果您执行这样的查询:

err = c.Find(Person{
    Name: "Alice",
}).All(&result)

那么当filter值被编组到BSON时,它只会包含一个"name"字段,因为Phone是它的零值,所以不会被编组。

当然,在插入/更新时使用 omitempty 可能不是您想要的,因此使用单一类型来表示和查询人员可能不够。通常,您应该 "tag" Person 您希望如何表示您的数据,并且您应该使用简单的 bson.M 值来查询,或者创建另一个结构来模拟您希望如何查询。

  1. Should I specify BOTH JSON and BSON keys like in json:"name" or are they interchangeable?

它们不可互换,所以如果您只指定 json 标签,bson 包不会使用(忽略)这些标签,同样,如果您只指定 bson标签,标准库的 encoding/json 包不会使用这些标签。它们是 2 个不同的标签,用于 2 个不同的目的,由 2 个不同的库(包)使用。

您可以指定也可以不指定。如果您从未打算将数据序列化为 JSON,则不必指定 json 标签。

mgo/bson 包用于对所有数据库命令和结果进行编码和解码,即使应用程序不直接使用该包也是如此。

复合文字 Person{ Name: "Alice" } returns 一个 Person 值,Phone 字段设置为 ""。 BSON 编码器将此值编码为逻辑值 {"Name": "Alice", "Phone": ""}。具有此值的查询 returns 所有名称等于 "Alice" 且 Phone 等于“”的文档。显然在集合中没有匹配此查询的文档。

查询文档必须有一个 Name 字段,只查询 Name 等于 "Alice" 和 Phone 的所有文档,任何值或根本没有设置。

Should I avoid the BSON import?

不用了,有用的时候直接用bson包。

Can I query for all matching patterns without using BSON or specifying the entire interface?

bson.M 类型通常是构造查询的最佳方式,但没有它也可以。例如,您可以像这样查询名称为 "Alice" 的所有文档:

c.Find(struct { Name string }{Name: "Alice"}).All(&result)

您也可以使用 map[string]interface{}:

c.Find(map[string]interface{}{"Name": "Alice"}).All(&result)

最后,您可以使用 BSON 编码器的 "omitempty" 功能从编码值中省略空字段。我不推荐这种方法,因为它会阻止您查询字段等于“”的文档。对于此方法,将结构类型更改为以下内容:

type Person struct {
    Name  string `bson:",omitempty"`
    Phone string `bson:",omitempty"`
}

Should I specify BOTH JSON and BSON keys like in json:"name" or are they interchangeable?

它们不可互换。根据需要为 BSON 编码器和 JSON 编码器指定标签。