Reputation: 2787
I'm learning how to use the community maintained mgo
repo linked here.
I've discovered through this 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)
Which will give me all Person
with name Alice
.
I have also discovered that I don't need BSON to do this query. Find()
takes any interface:
c.Find(Person{
Name: "Alice",
Phone: "1234",
}).All(&result)
Will also work, but only returning the specified exact query. If I leave out piece of the struct like this:
c.Find(Person{
Name: "Alice",
}).All(&result)
result
will be empty.
It seems to me that avoiding BSON is more intuitive and simpler. So my questions are:
json:"name"
or
are they interchangeable?Upvotes: 4
Views: 3042
Reputation: 120951
The mgo/bson package is used to encode and decode all database commands and results, even when the application does not use the package directly.
The composite literal Person{ Name: "Alice" }
returns a Person
value with the Phone
field set to ""
. The BSON encoder encodes this value to what is logically the value {"Name": "Alice", "Phone": ""}
. A query with this value returns all documents with Name equal "Alice" AND Phone equal to "". Apparently there are no documents that match this query in the collection.
The query document must have a Name field only to query all documents with Name equal "Alice" and Phone with any value or not set at all.
Should I avoid the BSON import?
No, use the bson package directly when it's helpful.
Can I query for all matching patterns without using BSON or specifying the entire interface?
The bson.M
type is usually the best way to construct queries, but you can do it without it. For example, you can query for all documents with name "Alice" like this:
c.Find(struct { Name string }{Name: "Alice"}).All(&result)
You can also use map[string]interface{}
:
c.Find(map[string]interface{}{"Name": "Alice"}).All(&result)
Finally, you can use the BSON encoder's "omitempty" feature to omit empty fields from the encoded value. I do not recommend this approach because it prevents you from querying for documents where the field is equal to "". Change the struct type to the following for this approach:
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?
They are not interchangeable. Specify the tags as needed for the BSON encoder and the JSON encoder.
Upvotes: 4
Reputation: 417612
- Should I avoid the BSON import?
I see no reason to do so. MongoDB (through mgo
) and BSON walk hand-in-hand. It doesn't matter if you import bson
or not, bson
will still be used under the hood (to serialize / represent the data sent back and forth).
- Can I query for all matching patterns wtihout using BSON or specifying the entire interface?
Yes, you can, if you use the omitempty
option when specifying the "bson"
tags, like this:
type Person struct {
Name string `bson:"name,omitempty"`
Phone string `bson:"phone,omitempty"`
}
Now if you do a query like this:
err = c.Find(Person{
Name: "Alice",
}).All(&result)
Then when the filter value is marshalled into BSON, it will only contain a "name"
field, because Phone
is its zero value, so it will not be marshaled.
Of course using omitempty
may not be what you want when you do insert / update, so using a single type for representing and querying persons may not be sufficient. Generally, you should "tag" Person
how you want to represent your data, and you should use simple bson.M
values to query, or create another struct that models how you want to query.
- Should I specify BOTH JSON and BSON keys like in
json:"name"
or are they interchangeable?
They are not interchangeable, so if you only specify json
tags, those are not used (ignored) by the bson
package, and similarly, if you only specify bson
tags, the encoding/json
package of the standard library will not use those. They are 2 different tags, used for 2 different purposes, used by 2 different libraries (packages).
You may or may not specify both. If you never intend to serialize your data into JSON, you don't have to specify json
tags.
Upvotes: 2