Skip to content

Commit 8a1b625

Browse files
authored
DOCSP-26442: use struct in projection pg (#219)
* DOCSP-26442: use struct in project pg * first pass fixes * DB PR fixes 1
1 parent 4c8b8f8 commit 8a1b625

File tree

2 files changed

+110
-98
lines changed

2 files changed

+110
-98
lines changed

source/fundamentals/crud/read-operations/project.txt

Lines changed: 77 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,44 @@ document from read operations.
2121
Sample Data
2222
~~~~~~~~~~~
2323

24-
To run the examples in this guide, load these documents into the
25-
``tea.ratings`` collection with the following
26-
snippet:
24+
The examples in this guide use the following ``Course`` struct as a model for documents
25+
in the ``courses`` collection:
2726

28-
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/projection.go
27+
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/projection.go
28+
:start-after: start-course-struct
29+
:end-before: end-course-struct
30+
:language: go
31+
:dedent:
32+
33+
The ``omitempty`` :ref:`struct tag<golang-struct-tags>` directs the
34+
driver to exclude fields when unmarshalling based on your projection
35+
specification.
36+
37+
To run the examples in this guide, load the sample data into the
38+
``db.courses`` collection with the following snippet:
39+
40+
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/projection.go
2941
:language: go
3042
:dedent:
3143
:start-after: begin insertDocs
3244
:end-before: end insertDocs
3345

34-
.. include:: /includes/fundamentals/tea-sample-data-ending.rst
46+
.. include:: /includes/fundamentals/automatic-db-coll-creation.rst
47+
48+
Each document contains a description of a university course that
49+
includes the course title, course ID, and maximum enrollment, corresponding to
50+
the ``title``, ``course_id``, and ``enrollment`` fields in each document.
3551

3652
Projection
3753
----------
3854

39-
A projection specifies which fields to return in matched documents. It
40-
contains field names followed by a ``1`` (to include) or ``0`` (to
41-
exclude). Projections can only include or exclude fields.
55+
A projection specifies which fields to return in matched documents. The
56+
projection document contains field names with a ``1`` to include the
57+
corresponding field or ``0`` to exclude it. If you are using an aggregation framework,
58+
you can also specify a projection to include newly computed fields.
4259

43-
You can specify a projection by passing one to the ``SetProjection()``
44-
method in the options of the following read operation methods:
60+
You can specify a projection by passing a projection document to the ``SetProjection()``
61+
method. The following read operations take an options object as a parameter:
4562

4663
- ``Find()``
4764
- ``FindOne()``
@@ -57,149 +74,134 @@ method in the options of the following read operation methods:
5774
Exclude a Field
5875
~~~~~~~~~~~~~~~
5976

60-
To exclude a field, pass the field you want to exclude and a ``0`` to
61-
the ``SetProjection()`` method. For all fields you don't explicitly
62-
list in the projection, the driver includes them.
77+
To exclude a field, pass the field you want to exclude with a ``0`` to
78+
the ``SetProjection()`` method. The driver includes all fields that are
79+
not explicitly excluded in the projection document, if you specify any
80+
fields to exclude.
6381

6482
Example
6583
```````
6684

67-
The following example excludes the ``rating`` from the matched documents
68-
from the ``Find()`` method:
85+
The following example excludes the ``course_id`` and ``enrollment``
86+
fields from the matched documents returned by the ``Find()`` method:
6987

7088
.. io-code-block::
7189
:copyable: true
7290

7391
.. input::
7492
:language: go
7593

76-
opts := options.Find().SetProjection(bson.D{{"rating", 0}})
77-
78-
cursor, err := coll.Find(context.TODO(), bson.D{}, opts)
94+
filter := bson.D{}
95+
opts := options.Find().SetProjection(bson.D{{"course_id", 0}, {"enrollment", 0}})
96+
97+
cursor, err := coll.Find(context.TODO(), filter, opts)
7998
if err != nil {
80-
panic(err)
99+
panic(err)
81100
}
82-
83-
var results []bson.D
101+
102+
var results []Course
84103
if err = cursor.All(context.TODO(), &results); err != nil {
85-
panic(err)
104+
panic(err)
86105
}
106+
87107
for _, result := range results {
88-
fmt.Println(result)
108+
res, _ := bson.MarshalExtJSON(result, false, false)
109+
fmt.Println(string(res))
89110
}
90111

91112
.. output::
92113
:language: none
93114
:visible: false
94115

95-
//results truncated
96-
[{_id ObjectID("...")} {type Masala}]
97-
[{_id ObjectID("...")} {type Assam}]
98-
[{_id ObjectID("...")} {type Oolong}]
99-
[{_id ObjectID("...")} {type Earl Grey}]
100-
[{_id ObjectID("...")} {type English Breakfast}]
116+
{"title":"Primate Behavior"}
117+
{"title":"Revolution and Reform"}
101118

102119
Include a Field
103120
~~~~~~~~~~~~~~~
104121

105-
To include a field, pass the field you want to include and a ``1`` to
106-
the ``SetProjection()`` method. For all fields you don't explicitly
107-
list in the projection, the driver excludes them.
108-
109-
.. important::
110-
111-
You can exclude the ``_id`` field even if you specified to include
112-
certain fields. By default, the driver includes the ``_id`` field.
113-
You must explicitly exclude the ``_id`` field if you do not want it
114-
returned.
122+
To include a field, pass the field you want to include with a ``1`` to
123+
the ``SetProjection()`` method. The driver excludes all fields that are
124+
not explicitly included in the projection document, if you specify any
125+
fields to include.
115126

116127
.. _golang-include-projection:
117128

118129
Example
119130
```````
120131

121-
The following example performs the following projection on the matched
122-
documents from the ``Find()`` method:
123-
124-
- Include the ``type`` and ``rating`` field
125-
- Exclude the ``_id`` field
132+
The following example includes only the ``title`` and ``enrollment`` fields
133+
from the matched documents returned by the ``Find()`` method:
126134

127135
.. io-code-block::
128136
:copyable: true
129137

130138
.. input::
131139
:language: go
132140

133-
opts := options.Find().SetProjection(bson.D{{"type", 1}, {"rating", 1}, {"_id", 0}})
134-
135-
cursor, err := coll.Find(context.TODO(), bson.D{}, opts)
141+
filter := bson.D{}
142+
opts := options.Find().SetProjection(bson.D{{"title", 1}, {"enrollment", 1}})
143+
144+
cursor, err := coll.Find(context.TODO(), filter, opts)
136145
if err != nil {
137-
panic(err)
146+
panic(err)
138147
}
139-
140-
var results []bson.D
148+
149+
var results []Course
141150
if err = cursor.All(context.TODO(), &results); err != nil {
142-
panic(err)
151+
panic(err)
143152
}
144153
for _, result := range results {
145-
fmt.Println(result)
154+
res, _ := bson.MarshalExtJSON(result, false, false)
155+
fmt.Println(string(res))
146156
}
147157

148158
.. output::
149159
:language: none
150160
:visible: false
151161

152-
[{type Masala} {rating 10}]
153-
[{type Assam} {rating 5}]
154-
[{type Oolong} {rating 7}]
155-
[{type Earl Grey} {rating 8}]
156-
[{type English Breakfast} {rating 5}]
162+
{"title":"Primate Behavior","enrollment":40}
163+
{"title":"Revolution and Reform","enrollment":12}
157164

158165
Aggregation
159166
~~~~~~~~~~~
160167

161-
You can also include the :manual:`$project </reference/operator/aggregation/project/>`
168+
You can also create a :manual:`$project </reference/operator/aggregation/project/>`
162169
stage to specify a projection in an aggregation pipeline.
163170

164171
Example
165172
```````
166173

167-
The following example performs the following projection on the matched
168-
documents from the ``Aggregate()`` method:
169-
170-
- Include the ``type`` and ``rating`` field
171-
- Exclude the ``_id`` field
174+
The following example includes only the ``title`` and ``course_id`` fields
175+
from the matched documents returned by the ``Aggregate()`` method:
172176

173177
.. io-code-block::
174178
:copyable: true
175179

176180
.. input::
177181
:language: go
178182

179-
projectStage := bson.D{{"$project", bson.D{{"type", 1}, {"rating", 1}, {"_id", 0}}}}
180-
183+
projectStage := bson.D{{"$project", bson.D{{"title", 1}, {"course_id", 1}}}}
184+
181185
cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{projectStage})
182186
if err != nil {
183-
panic(err)
187+
panic(err)
184188
}
185-
186-
var results []bson.D
189+
190+
var results []Course
187191
if err = cursor.All(context.TODO(), &results); err != nil {
188-
panic(err)
192+
panic(err)
189193
}
190194
for _, result := range results {
191-
fmt.Println(result)
195+
res, _ := bson.MarshalExtJSON(result, false, false)
196+
fmt.Println(string(res))
192197
}
193198

194199
.. output::
195200
:language: none
196201
:visible: false
197202

198-
[{type Masala} {rating 10}]
199-
[{type Assam} {rating 5}]
200-
[{type Oolong} {rating 7}]
201-
[{type Earl Grey} {rating 8}]
202-
[{type English Breakfast} {rating 5}]
203+
{"title":"Primate Behavior","course_id":"PSY2030"}
204+
{"title":"Revolution and Reform","course_id":"HIST3080"}
203205

204206
Additional Information
205207
----------------------

source/includes/fundamentals/code-snippets/CRUD/projection.go

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ import (
1111
"go.mongodb.org/mongo-driver/mongo/options"
1212
)
1313

14+
// start-course-struct
15+
type Course struct {
16+
Title string `bson:"title,omitempty"`
17+
CourseId string `bson:"course_id,omitempty"`
18+
Enrollment int32 `bson:"enrollment,omitempty"`
19+
}
20+
21+
// end-course-struct
22+
1423
func main() {
1524
var uri string
1625
if uri = os.Getenv("MONGODB_URI"); uri == "" {
@@ -28,81 +37,82 @@ func main() {
2837
}
2938
}()
3039

31-
client.Database("tea").Collection("ratings").Drop(context.TODO())
32-
3340
// begin insertDocs
34-
coll := client.Database("tea").Collection("ratings")
41+
coll := client.Database("db").Collection("courses")
3542
docs := []interface{}{
36-
bson.D{{"type", "Masala"}, {"rating", 10}},
37-
bson.D{{"type", "Assam"}, {"rating", 5}},
38-
bson.D{{"type", "Oolong"}, {"rating", 7}},
39-
bson.D{{"type", "Earl Grey"}, {"rating", 8}},
40-
bson.D{{"type", "English Breakfast"}, {"rating", 5}},
43+
Course{Title: "Primate Behavior", CourseId: "PSY2030", Enrollment: 40},
44+
Course{Title: "Revolution and Reform", CourseId: "HIST3080", Enrollment: 12},
4145
}
4246

4347
result, err := coll.InsertMany(context.TODO(), docs)
48+
//end insertDocs
49+
4450
if err != nil {
4551
panic(err)
4652
}
4753
fmt.Printf("Number of documents inserted: %d\n", len(result.InsertedIDs))
48-
//end insertDocs
4954

50-
fmt.Println("Exclude Projection:")
55+
fmt.Println("\nExclude Projection:\n")
5156
{
5257
//begin exclude projection
53-
opts := options.Find().SetProjection(bson.D{{"rating", 0}})
58+
filter := bson.D{}
59+
opts := options.Find().SetProjection(bson.D{{"course_id", 0}, {"enrollment", 0}})
5460

55-
cursor, err := coll.Find(context.TODO(), bson.D{}, opts)
61+
cursor, err := coll.Find(context.TODO(), filter, opts)
5662
if err != nil {
5763
panic(err)
5864
}
5965

60-
var results []bson.D
66+
var results []Course
6167
if err = cursor.All(context.TODO(), &results); err != nil {
6268
panic(err)
6369
}
6470
for _, result := range results {
65-
fmt.Println(result)
71+
res, _ := bson.MarshalExtJSON(result, false, false)
72+
fmt.Println(string(res))
6673
}
6774
//end exclude projection
6875
}
6976

70-
fmt.Println("Include Projection:")
77+
fmt.Println("\nInclude Projection:\n")
7178
{
7279
//begin include projection
73-
opts := options.Find().SetProjection(bson.D{{"type", 1}, {"rating", 1}, {"_id", 0}})
80+
filter := bson.D{}
81+
opts := options.Find().SetProjection(bson.D{{"title", 1}, {"enrollment", 1}})
7482

75-
cursor, err := coll.Find(context.TODO(), bson.D{}, opts)
83+
cursor, err := coll.Find(context.TODO(), filter, opts)
7684
if err != nil {
7785
panic(err)
7886
}
7987

80-
var results []bson.D
88+
var results []Course
8189
if err = cursor.All(context.TODO(), &results); err != nil {
8290
panic(err)
8391
}
8492
for _, result := range results {
85-
fmt.Println(result)
93+
res, _ := bson.MarshalExtJSON(result, false, false)
94+
fmt.Println(string(res))
8695
}
8796
//end include projection
8897
}
8998

90-
fmt.Println("Aggregation Projection:")
99+
fmt.Println("\nAggregation Projection:\n")
91100
{
92101
// begin aggregate projection
93-
projectStage := bson.D{{"$project", bson.D{{"type", 1}, {"rating", 1}, {"_id", 0}}}}
102+
projectStage := bson.D{{"$project", bson.D{{"title", 1}, {"course_id", 1}}}}
94103

95104
cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{projectStage})
96105
if err != nil {
97106
panic(err)
98107
}
99108

100-
var results []bson.D
109+
var results []Course
101110
if err = cursor.All(context.TODO(), &results); err != nil {
102111
panic(err)
103112
}
104113
for _, result := range results {
105-
fmt.Println(result)
114+
res, _ := bson.MarshalExtJSON(result, false, false)
115+
fmt.Println(string(res))
106116
}
107117
// end aggregate projection
108118
}

0 commit comments

Comments
 (0)