-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathbson.txt
358 lines (261 loc) · 11.4 KB
/
bson.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
.. _golang-bson:
==============
Work with BSON
==============
.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol
.. facet::
:name: genre
:values: reference
.. meta::
:keywords: code examples, serialization
:description: Learn how the Go driver handles BSON data conversion, including marshalling and unmarshalling, and how to use struct tags and BSON options.
Overview
--------
In this guide, you can learn about how the {+driver-short+} handles conversions
between BSON and Go types. The process of converting a Go type to
BSON is called **marshalling**, while the reverse process is called **unmarshalling**.
The following sections explain how the {+driver-short+} represents BSON data
and how you can adjust default marshalling and unmarshalling behaviors.
.. _golang-bson-types:
Data Types
----------
MongoDB stores documents in a binary representation called :manual:`BSON
</reference/bson-types/>` that allows for easy and flexible data processing.
The {+driver-short+} provides four main types for working with BSON data:
- ``D``: An ordered representation of a BSON document (slice)
- ``M``: An unordered representation of a BSON document (map)
- ``A``: An ordered representation of a BSON array
- ``E``: A single element inside a D type
The following example demonstrates how to construct a query filter by using the
``bson.D`` type to match documents in which the ``quantity`` field value is greater
than 100:
.. code-block:: go
filter := bson.D{{"quantity", bson.D{{"$gt", 100}}}}
To learn more about how the {+driver-short+} handles BSON data, see the
`bson package API documentation <{+api+}/bson>`__.
.. _golang-struct-tags:
Struct Tags
-----------
In Go, a **struct** is a collection of data fields with declared data
types. You can modify the default marshalling and unmarshalling behavior of
a struct field by using **struct tags**, which are optional pieces of metadata
attached to struct fields. The most common use of struct tags is for specifying
the field name in the BSON document that corresponds to the struct field.
The following table describes the additional struct tags that you can
use in the {+driver-short+}:
.. list-table::
:widths: 25 75
:header-rows: 1
* - Struct Tag
- Description
* - ``omitempty``
- The field will not be marshaled if it is set to the zero value
corresponding to the field type. To globally prevent the driver from
marshaling fields set to a zero value, you can set the ``OmitEmpty``
BSON option. To learn more about how to set the ``OmitEmpty`` BSON option,
see the example in the :ref:`BSON Options <golang-bson-options>`
section of this page.
* - ``minsize``
- If the field is type ``int64``, ``uint``, ``uint32``, or ``uint64`` and
the value of the field can fit in a signed ``int32``, the field will be
serialized as a BSON ``int32`` rather than a BSON ``int64``. If the value
can't fit in a signed ``int32``, this tag is ignored.
* - ``truncate``
- If the field type is a non-float numeric type, BSON doubles
unmarshalled into that field will be truncated at the decimal point.
* - ``inline``
- If the field type is a struct or map field, the field will be
flattened when marshalling and unflattened when unmarshalling.
If you don't specify struct tags, the {+driver-short+} marshals structs by using
the following rules:
#. The driver only marshals and unmarshals exported fields.
#. The driver generates a BSON key by using the lowercase of the
corresponding struct field.
#. The driver marshals embedded struct fields as subdocuments. Each key
is the lowercase of the field's type.
#. The driver marshals a pointer field as the underlying type if the pointer
is non-nil. If the pointer is nil, the driver marshals it as a BSON null
value.
#. When unmarshalling, the {+driver-short+} follows `these D/M type mappings
<{+api+}/bson#hdr-Native_Go_Types>`_
for fields of type ``interface{}``. The driver unmarshals BSON documents
unmarshalled into an ``interface{}`` field as a ``D`` type.
.. tabs::
.. tab:: Struct Tags
:tabid: struct-tags
The following example demonstrates how the {+driver-short+} marshals a
struct with various struct tags:
.. code-block:: go
type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string `bson:"first_name,omitempty"`
LastName string `bson:"last_name,omitempty"`
Address Address `bson:"inline"`
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)
The corresponding BSON representation looks like this:
.. code-block:: json
:copyable: false
{
"_id" : ObjectId("..."),
"first_name" : "Arthur",
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA",
"age" : 8
}
In this example, struct tags make the driver:
- Set custom BSON field names such as ``first_name``
- Omit the empty ``LastName`` field
- Flatten the nested struct and bring all fields up to the top
level
.. tabs::
.. tab:: No Struct Tags
:tabid: no-struct-tags
The following example demonstrates how the {+driver-short+} marshals
a struct without any struct tags:
.. code-block:: go
type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string
LastName string
Address Address
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)
The corresponding BSON representation looks like this:
.. code-block:: json
:copyable: false
{
"_id" : ObjectId("..."),
"firstname" : "Arthur",
"lastname" : "",
"address": {
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA"
},
"age" : 8
}
Without struct tags, the driver:
- Sets the lowercase of the struct fields as the BSON field names
- Includes an empty ``lastname`` field
- Stores the ``Address`` field as a nested value
.. _golang-bson-options:
BSON Options
------------
You can specify BSON options to adjust the marshalling and unmarshalling behavior of
your ``Client`` instance. To set BSON options on your ``Client``, create and configure
a ``BSONOptions`` instance.
This example performs the following actions:
- Creates a ``BSONOptions`` instance by configuring the following settings:
- Sets the ``UseJSONStructTags`` field to ``true``, which instructs the driver
to use the ``"json"`` struct tag if a ``"bson"`` struct tag is not specified
- Sets the ``NilSliceAsEmpty`` field to ``true``, which instructs the driver
to marshal ``nil`` Go slices as empty BSON arrays
- Sets the ``OmitEmpty`` field to ``true``, which instructs the driver to globally omit
empty values from the marshaled BSON, rather than set empty values to ``null``
- Passes the ``BSONOptions`` instance to the ``SetBSONOptions()`` helper method to specify
a ``ClientOptions`` instance
- Creates a ``Client`` to apply the specified BSON marshalling and unmarshalling behavior
.. code-block:: go
bsonOpts := &options.BSONOptions {
UseJSONStructTags: true,
NilSliceAsEmpty: true,
OmitEmpty: true,
}
clientOpts := options.Client().
ApplyURI("<connection string>").
SetBSONOptions(bsonOpts)
client, err := mongo.Connect(clientOpts)
.. tip::
To learn more about the ``BSONOptions`` type, see the
`BSONOptions API documentation <{+api+}/mongo/options#BSONOptions>`__.
For an example that specifies a ``BSONOptions`` instance and creates a client with
these options, see the `Connect() BSONOptions example
<{+api+}/mongo#example-Connect-BSONOptions>`__.
.. _golang-bson-unmarshalling:
Unmarshalling
-------------
You can unmarshal BSON documents by using the ``Decode()`` method on the
result of the ``FindOne`` method or any ``*mongo.Cursor`` instance.
The ``Decode()`` method returns an ``error`` type which
contains one of the following values:
- ``nil`` if a document matched your query, and there were no errors
retrieving and unmarshalling the document.
- If the driver retrieved your document but could not unmarshal your result, the
``Decode()`` method returns the unmarshalling error.
- If there was an error retrieving your document during execution of the
``FindOne()`` method, the error propagates to the ``Decode()`` method and
the ``Decode()`` method returns the error.
When used on the ``SingleResult`` type returned by the ``FindOne()``
method, ``Decode()`` can also return the ``ErrNoDocuments`` error if no
documents matched the query filter.
The following example demonstrates how you can use the ``Decode()``
method to unmarshal and read the result of a simple ``FindOne()``
operation:
.. io-code-block::
:copyable: true
.. input::
:language: go
coll := client.Database("db").Collection("students")
filter := bson.D{{"age", 8}}
var result bson.D
err := coll.FindOne(context.TODO(), filter).Decode(&result)
fmt.Println(result)
.. output::
:language: none
:visible: false
[{_id ObjectID("...")} {first_name Arthur} {street 1 Fern Way} {city Elwood City} {state PA} {age 8}]
The ``Cursor`` type also uses the ``All()`` method, which unmarshals all
documents stored in the cursor into an array at the same time.
The ``bson`` package includes a family of ``Marshal()`` and ``Unmarshal()``
methods that work with BSON-encoded data of ``[]byte`` type.
The following code demonstrates how you can unmarshal BSON back into a
user-defined struct by using methods from the ``bson`` package:
.. io-code-block::
:copyable: true
.. input::
:language: go
type Item struct {
Category string
Quantity int32
}
doc, err := bson.Marshal(bson.D{{"category", "plate"}, {"quantity", 6}})
var test Item
err = bson.Unmarshal(doc, &test)
fmt.Printf("Unmarshalled Struct:\n%+v\n", test)
.. output::
:language: none
:visible: false
Unmarshalled Struct:
{Category:plate Quantity:6}
.. note::
You can use the ``Raw`` type to retrieve elements from a BSON
document byte slice without unmarshalling it to a Go type. This type
allows you to look up individual elements without unmarshalling
the entire BSON document.
To learn more about the marshalling and unmarshalling methods used with the
``Cursor`` type, see the `Cursor API documentation <{+api+}/mongo#Cursor>`__
To learn more about the marshalling and unmarshalling methods in the
``bson`` package, see the `bson API documentation
<{+api+}/bson#hdr-Marshalling_and_Unmarshalling>`_