Skip to content

Commit fc76db0

Browse files
authored
Merge pull request #10 from rustagir/DOCSP-13853-marshal-fundies
DOCSP 13853: working with bson pg
2 parents 57ce697 + 698b515 commit fc76db0

File tree

2 files changed

+298
-1
lines changed

2 files changed

+298
-1
lines changed

source/fundamentals.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Fundamentals
1010

1111
/fundamentals/connection
1212
/fundamentals/auth
13-
13+
/fundamentals/bson
1414

1515
..
1616
/fundamentals/enterprise-auth

source/fundamentals/bson.txt

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
=================
2+
Working with BSON
3+
=================
4+
5+
.. default-domain:: mongodb
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 2
11+
:class: singlecol
12+
13+
Overview
14+
--------
15+
16+
In this guide, you can learn about how the Go Driver handles conversions
17+
between BSON and Go values. The process of converting a Go value to
18+
BSON is called **marshalling**, while the reverse process is called **unmarshalling**.
19+
20+
You should read this guide if you want to learn more about how the Go Driver
21+
represents BSON data or need to adjust default marshalling
22+
and unmarshalling behaviors.
23+
24+
Data Types
25+
----------
26+
27+
MongoDB stores documents in a binary representation called :manual:`BSON
28+
</reference/bson-types/>` that allows for easy and flexible data processing.
29+
30+
The Go Driver provides four main types for working with BSON data:
31+
32+
- ``D``: An ordered representation of a BSON document (slice)
33+
- ``M``: An unordered representation of a BSON document (map)
34+
- ``A``: An ordered representation of a BSON array
35+
- ``E``: A single element inside a D type
36+
37+
The following example demonstrates how to construct a query filter using the
38+
``bson.D`` type to match documents with a ``quantity`` field value greater
39+
than 100:
40+
41+
.. code-block:: go
42+
43+
filter := bson.D{{"quantity", bson.D{{"$gt", 100}}}}
44+
45+
For more information on how the Go Driver handles BSON data, see the
46+
`bson package API documentation
47+
<https://pkg.go.dev/go.mongodb.org/mongo-driver/bson>`_.
48+
49+
Struct Tags
50+
-----------
51+
52+
In Go, a **struct** is a collection of data fields with declared data
53+
types. The Go Driver can marshal/unmarshal structs and other native Go
54+
types to/from BSON using a `configurable codec system <https://pkg.go.dev/go.mongodb.org/mongo-driver/bson/bsoncodec>`_.
55+
56+
You can modify the default marshalling and unmarshalling behavior of the Go Driver using
57+
**struct tags**, which are optional pieces of metadata attached to
58+
struct fields. The most common use of struct tags is for specifying the
59+
field name in the BSON document that corresponds to the struct field.
60+
The following table describes the additional struct tags that you can
61+
use with the Go Driver:
62+
63+
.. list-table::
64+
:widths: 25 75
65+
:header-rows: 1
66+
67+
* - Struct Tag
68+
- Description
69+
70+
* - ``omitempty``
71+
- The field will not be marshalled if it is set to the zero value
72+
corresponding to the field type.
73+
74+
* - ``minsize``
75+
- If the field type is type int64, uint, uint32, or uint64 and the value of
76+
the field can fit in a signed int32, the field will be serialized
77+
as a BSON int32 rather than a BSON int64. If the value can't fit
78+
in a signed int32, this tag is ignored.
79+
80+
* - ``truncate``
81+
- If the field type is a non-float numeric type, BSON doubles
82+
unmarshalled into that field will be trucated at the decimal point.
83+
84+
* - ``inline``
85+
- If the field type is a struct or map field, the field will be
86+
"flattened" when marshalling and "un-flattened" when unmarshalling.
87+
88+
Without additional instruction from struct tags, the Go
89+
Driver will marshal structs using the following rules:
90+
91+
#. The Go Driver only marshals and unmarshals exported fields.
92+
93+
#. The Go Driver generates BSON key using the lowercase of the
94+
corresponding struct field.
95+
96+
#. The Go Driver marshals embedded struct fields as subdocuments.
97+
Each key is the lowercase of the field's type.
98+
99+
#. The Go Driver marshals a pointer field as the underlying type if the
100+
pointer is non-nil. If the pointer is nil, the driver marshals it as a BSON null
101+
value.
102+
103+
#. When unmarshalling, the Go Driver follows `these D/M type mappings
104+
<https://pkg.go.dev/go.mongodb.org/mongo-driver/bson#hdr-Native_Go_Types>`_
105+
for fields of type ``interface{}``. The driver unmarshals BSON documents
106+
unmarshalled into an ``interface{}`` field as a ``D`` type.
107+
108+
.. tabs::
109+
110+
.. tab:: Struct Tags
111+
:tabid: struct-tags
112+
113+
The following example demonstrates how the Go Driver marshals a
114+
struct with various struct tags:
115+
116+
.. code-block:: go
117+
118+
type Address struct {
119+
Street string
120+
City string
121+
State string
122+
}
123+
124+
type Student struct {
125+
FirstName string `bson:"first_name,omitempty"`
126+
LastName string `bson:"last_name,omitempty"`
127+
Address Address `bson:"inline"`
128+
Age int
129+
}
130+
...
131+
132+
coll := client.Database("school").Collection("students")
133+
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
134+
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
135+
_, err = coll.InsertOne(context.TODO(), student1)
136+
137+
The corresponding BSON representation looks like this:
138+
139+
.. code-block:: json
140+
:copyable: false
141+
142+
{
143+
"_id" : ObjectId("..."),
144+
"first_name" : "Arthur",
145+
"street" : "1 Lakewood Way",
146+
"city" : "Elwood City",
147+
"state" : "PA",
148+
"age" : 8
149+
}
150+
151+
In this example, struct tags make the driver:
152+
153+
- Set custom BSON field names such as ``first_name``
154+
- Omit the empty ``LastName`` field
155+
- Flatten the nested struct and bring all fields up to the top
156+
level
157+
158+
.. tabs::
159+
160+
.. tab:: No Struct Tags
161+
:tabid: no-struct-tags
162+
163+
The following example demonstrates how the Go Driver marshals a
164+
struct without any struct tags:
165+
166+
.. code-block:: go
167+
168+
type Address struct {
169+
Street string
170+
City string
171+
State string
172+
}
173+
174+
type Student struct {
175+
FirstName string
176+
LastName string
177+
Address Address
178+
Age int
179+
}
180+
...
181+
182+
coll := client.Database("school").Collection("students")
183+
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
184+
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
185+
_, err = coll.InsertOne(context.TODO(), student1)
186+
187+
The corresponding BSON representation looks like this:
188+
189+
.. code-block:: json
190+
:copyable: false
191+
192+
{
193+
"_id" : ObjectId("..."),
194+
"firstname" : "Arthur",
195+
"lastname" : "",
196+
"address": {
197+
"street" : "1 Lakewood Way",
198+
"city" : "Elwood City",
199+
"state" : "PA"
200+
},
201+
"age" : 8
202+
}
203+
204+
Without struct tags, the driver:
205+
206+
- Sets the lowercase of the struct fields as the BSON field names
207+
- Includes an empty ``lastname`` field
208+
- Stores the ``Address`` field as a nested value
209+
210+
Unmarshalling
211+
-------------
212+
213+
You can unmarshal BSON documents by using the ``Decode()`` method on the
214+
result of the ``FindOne`` method or any ``*mongo.Cursor`` instance.
215+
216+
The ``Decode()`` method returns an ``error`` type which
217+
contains one of the following values:
218+
219+
- ``nil`` if a document matched your query, and there were no errors
220+
retrieving and unmarshalling the document.
221+
- If the driver retrieved your document but could not unmarshal your result, the
222+
``Decode()`` method returns the unmarshalling error.
223+
- If there was an error retrieving your document during execution of the
224+
``FindOne()`` method, the error propagates to the ``Decode()`` method and
225+
the ``Decode()`` method returns the error.
226+
227+
When used on the ``SingleResult`` type returned by the ``FindOne()``
228+
method, ``Decode()`` can also return the ``ErrNoDocuments`` error if no
229+
documents matched the query filter.
230+
231+
The following example demonstrates how you can use the ``Decode()``
232+
method to unmarshal and read the result of a simple ``FindOne()``
233+
operation:
234+
235+
.. code-block:: go
236+
237+
coll := client.Database("school").Collection("students")
238+
filter := bson.D{{"age", 8}}
239+
240+
var result bson.D
241+
err := coll.FindOne(context.TODO(), filter).Decode(&result)
242+
...
243+
244+
fmt.Println(result)
245+
246+
The output of the preceding code should look like this:
247+
248+
.. code-block:: none
249+
250+
[{_id ObjectID("...")} {first_name Arthur} {street 1 Fern Way} {city Elwood City} {state PA} {age 8}]
251+
252+
The ``Cursor`` type also uses the ``All()`` method, which unmarshals all
253+
documents stored in the cursor into an array at the same time.
254+
255+
The ``bson`` package includes a family of
256+
``Marshal()`` and ``Unmarshal()`` methods that work with BSON-encoded data
257+
of ``[]byte`` type.
258+
259+
The following code demonstrates how you can unmarshal BSON back into a
260+
user-defined struct by using methods from the ``bson`` package:
261+
262+
.. code-block:: go
263+
264+
type Item struct {
265+
Category string
266+
Quantity int32
267+
}
268+
...
269+
270+
doc, err := bson.Marshal(bson.D{{"category", "plate"}, {"quantity", 6}})
271+
...
272+
var test Item
273+
err = bson.Unmarshal(doc, &test)
274+
...
275+
fmt.Printf("Unmarshalled Struct:\n%+v\n", test)
276+
277+
The output of the preceding code should look like this:
278+
279+
.. code-block:: none
280+
281+
Unmarshalled Struct:
282+
{Category:plate Quantity:6}
283+
284+
.. note::
285+
286+
You can use the ``Raw`` type to retrieve elements from a BSON
287+
document byte slice without unmarshalling it to a Go value. This can
288+
be useful if you need to look up individual elements without
289+
unmarshalling the entire BSON document.
290+
291+
For more information on the marshalling and unmarshalling methods used with the
292+
``Cursor`` type, see the `Cursor API documentation
293+
<https://pkg.go.dev/go.mongodb.org/[email protected]/mongo#Cursor>`_
294+
295+
For more information on the marshalling and unmarshalling methods in the
296+
``bson`` package, see the `bson API documentation
297+
<https://pkg.go.dev/go.mongodb.org/[email protected]/bson#hdr-Marshalling_and_Unmarshalling>`_

0 commit comments

Comments
 (0)