Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contains a struct tag that maps the ``WordCount`` field to the BSON
field name ``word_count``. By default, the driver marshals the other
fields as the lowercase of the struct field name:

.. literalinclude:: /includes/usage-examples/code-snippets/struct-tag.go
.. literalinclude:: /includes/usage-examples/code-snippets/structTag.go
:start-after: begin struct
:end-before: end struct
:language: go
Expand All @@ -32,13 +32,13 @@ struct field as ``word_count``:

.. include:: /includes/usage-examples/run-example-tip.rst

.. literalinclude:: /includes/usage-examples/code-snippets/struct-tag.go
.. literalinclude:: /includes/usage-examples/code-snippets/structTag.go
:start-after: begin create and insert
:end-before: end create and insert
:language: go
:dedent:

View a `fully runnable example. <{+example+}/struct-tag.go>`__
View a `fully runnable example. <{+example+}/structTag.go>`__

Expected Result
---------------
Expand Down
67 changes: 38 additions & 29 deletions source/data-formats/struct-tagging.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,59 @@ Use Struct Tags
You can specify the way that the Go Driver converts Go
structs to :manual:`BSON </reference/bson-types/>` by using struct tags.

Example
-------
.. TODO: Add the Usage Examples intro include once it is merged

The following code declares a struct of type ``BlogPost``. This struct
contains a struct tag that maps the ``WordCount`` field to the BSON
field name ``word_count``. By default, the driver marshals the other
fields as the lowercase of the struct field name:

.. literalinclude:: /includes/usage-examples/code-snippets/struct-tag.go
:start-after: begin struct
:end-before: end struct
:language: go
:dedent:
Example: Full File
------------------

.. include:: /includes/usage-examples/example-intro.rst

This example declares a struct of type ``Restaurant`` with the
following struct tags:

- A struct tag that maps the ``RestaurantId`` field to the BSON
field name ``restaurant_id``. By default, the driver marshals the other
fields as the lowercase of the struct field name.

- The ``omitempty`` struct tag omits the corresponding field from the
inserted document when left empty.

The following example creates a ``BlogPost`` instance and inserts it
into the ``posts`` collection. During the insert operation, the driver
interprets the struct tag to marshal the ``WordCount``
struct field as ``word_count``:
The following code shows the ``Restaurant`` struct used in the example:

.. literalinclude:: /includes/usage-examples/code-snippets/struct-tag.go
:start-after: begin create and insert
:end-before: end create and insert
.. literalinclude:: /includes/usage-examples/code-snippets/structTagStruct.go
:language: go
:dedent:

View a `fully runnable example. <{+example+}/struct-tag.go>`__
The following example creates a ``Restaurant`` instance and inserts it
into the ``restaurants`` collection. During the insert operation, the driver
interprets the struct tags to marshal the ``RestaurantId``
struct field as ``restaurant_id`` and omits fields that are left empty in the
sample document:

.. io-code-block::
:copyable: true

.. input:: /includes/usage-examples/code-snippets/structTag.go
:language: go
:dedent:

.. output::
:language: none
:visible: false

Document inserted with ID: ObjectID("...")

Expected Result
---------------

After you run the full example, you can find the following document
in the ``posts`` collection:
in the ``restaurants`` collection:

.. code-block:: json
:copyable: false

{
"_id" : ObjectId("..."),
"title" : "Annuals vs. Perennials?",
"author" : "Sam Lee",
"word_count" : 682,
"lastupdated": ...,
"tags" : ["seasons", "gardening", "flower"]
"name" : "Amazing Pizza",
"restaurant_id" : "123456789",
"cuisine" : "American
}

For an example on how to find a document, see the :ref:`golang-find-one` guide.
Expand Down
87 changes: 0 additions & 87 deletions source/includes/usage-examples/code-snippets/struct-tag.go

This file was deleted.

68 changes: 68 additions & 0 deletions source/includes/usage-examples/code-snippets/structTag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Specifies struct tags on a struct by using the Go driver
package main

import (
"context"
"fmt"
"log"
"os"

"github.com/joho/godotenv"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)

// Specifies a different name for RestaurantID
// and marks certain fields as omitempty
type Restaurant struct {
Name string
RestaurantId string `bson:"restaurant_id,omitempty"`
Comment on lines +18 to +19
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the BSON struct tag intentionally omitted on Name?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to show user that you don't have to include a struct tag if you're fine with how the field will be marshaled.

Cuisine string `bson:"cuisine,omitempty"`
Address interface{} `bson:"address,omitempty"`
Copy link
Collaborator

@matthewdale matthewdale Jul 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: The any alias for interface{} is available in all Go versions supported by the Go Driver now. The any syntax is easier to read than interface{}, so we should transition to using any at some point. It doesn't need to be in this PR, just wanted to bring it up.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can leave this for a future piece of work, as we would probably want to make this update in the rest of the Go docs. Is this any alias just used when creating structs? I can create a ticket!

Copy link
Collaborator

@matthewdale matthewdale Jul 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The any alias can be used anywhere interface{} can be used (structs, functions, variables, etc) and has an identical meaning to interface{} (see the docs here). We're currently working on replacing all occurrences of interface{} with any in the Go Driver code because it's easier to read.

Edit: Making a ticket for that change sounds like a great idea!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Borough string `bson:"borough,omitempty"`
Grades []interface{} `bson:"grades,omitempty"`
}

func main() {
if err := godotenv.Load(); err != nil {
log.Println("No .env file found")
}

var uri string
if uri = os.Getenv("MONGODB_URI"); uri == "" {
log.Fatal("You must set your 'MONGODB_URI' environment variable. See\n\t https://www.mongodb.com/docs/drivers/go/current/usage-examples/#environment-variable")
}

client, err := mongo.Connect(options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}
defer func() {
if err = client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}()

coll := client.Database("sample_restaurants").Collection("restaurants")

// Creates a Restaurant document

newRestaurant := Restaurant{
Name: "Amazing Pizza",
RestaurantId: "123456789",
Cuisine: "American",
}

// Inserts the sample document describing a restaurant into the collection

result, err := coll.InsertOne(context.TODO(), newRestaurant)
if err != nil {
panic(err)
}

// Prints the ID of the inserted document
fmt.Printf("Document inserted with ID: %s\n", result.InsertedID)

// When you run this file, it should print:
// Document inserted with ID: ObjectID("...")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type Restaurant struct {
Name string
RestaurantId string `bson:"restaurant_id,omitempty"`
Cuisine string `bson:"cuisine,omitempty"`
Address interface{} `bson:"address,omitempty"`
Borough string `bson:"borough,omitempty"`
Grades []interface{} `bson:"grades,omitempty"`
}
Loading