Skip to content

Commit 34fb046

Browse files
DOCSP-13833 crud cursor (#79)
* Added CRUD Cursor page
1 parent 94a1c53 commit 34fb046

File tree

5 files changed

+300
-8
lines changed

5 files changed

+300
-8
lines changed

source/fundamentals/bson.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _bson-golang:
2+
13
==============
24
Work with BSON
35
==============
@@ -21,6 +23,8 @@ You should read this guide if you want to learn more about how the Go Driver
2123
represents BSON data or need to adjust default marshalling
2224
and unmarshalling behaviors.
2325

26+
.. _bson-types:
27+
2428
Data Types
2529
----------
2630

source/fundamentals/crud/read-operations.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Read Operations
66

77
- :doc:`/fundamentals/crud/read-operations/count`
88
- :doc:`/fundamentals/crud/read-operations/retrieve`
9+
- :doc:`/fundamentals/crud/read-operations/cursor`
910
- :doc:`/fundamentals/crud/read-operations/distinct`
1011
- :doc:`/fundamentals/crud/read-operations/sort`
1112
- :doc:`/fundamentals/crud/read-operations/skip`
@@ -14,20 +15,19 @@ Read Operations
1415
- :doc:`/fundamentals/crud/read-operations/text`
1516

1617
..
17-
- :doc:`/fundamentals/crud/read-operations/cursor`
1818
- :doc:`/fundamentals/crud/read-operations/geo`
1919

2020
.. toctree::
2121
:caption: Read Operations
2222

2323
/fundamentals/crud/read-operations/count
2424
/fundamentals/crud/read-operations/retrieve
25+
/fundamentals/crud/read-operations/cursor
2526
/fundamentals/crud/read-operations/distinct
2627
/fundamentals/crud/read-operations/sort
2728
/fundamentals/crud/read-operations/skip
2829
/fundamentals/crud/read-operations/limit
2930
/fundamentals/crud/read-operations/project
3031
/fundamentals/crud/read-operations/text
3132
..
32-
/fundamentals/crud/read-operations/cursor
3333
/fundamentals/crud/read-operations/geo
Lines changed: 139 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,145 @@
1+
.. _cursor-golang:
2+
13
=========================
24
Access Data From a Cursor
35
=========================
46

57
.. default-domain:: mongodb
68

7-
Read operations that return multiple documents do not immediately return
8-
all values matching the query.
9+
.. contents:: On this page
10+
:local:
11+
:backlinks: none
12+
:depth: 2
13+
:class: singlecol
14+
15+
Overview
16+
--------
17+
18+
In this guide, you can learn how to access data with a **cursor**.
19+
20+
A cursor is a mechanism that allows an application to iterate over
21+
database results while holding only a subset of them in memory at a
22+
given time. Read operations that match multiple documents use a cursor
23+
to return those documents in batches as opposed to all at once.
24+
25+
Sample Cursor
26+
~~~~~~~~~~~~~
27+
28+
Each section uses the following ``cursor`` variable, which is a
29+
``Cursor`` struct that contains all the documents in a collection:
30+
31+
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/cursor.go
32+
:language: go
33+
:dedent:
34+
:start-after: begin find
35+
:end-before: end find
36+
37+
.. important::
38+
39+
A cursor is not goroutine safe. Do not use the same cursor in
40+
multiple goroutines at the same time.
41+
42+
.. _individual-documents-golang:
43+
44+
Retrieve Documents Individually
45+
-------------------------------
46+
47+
To retrieve documents from your cursor individually while blocking the
48+
current goroutine, use the ``Next()`` method.
49+
50+
The method returns a document if each of the following is true:
51+
52+
- A document is currently or will later be available
53+
- No errors occurred
54+
- The context didn't expire
55+
56+
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/cursor.go
57+
:language: go
58+
:dedent:
59+
:start-after: begin cursor next
60+
:end-before: end cursor next
61+
62+
Tailable Cursor
63+
~~~~~~~~~~~~~~~
64+
65+
To attempt retrieving a document from a :manual:`tailable cursor
66+
</core/tailable-cursors/>`, use the ``TryNext()`` method.
67+
68+
The method returns a document if each of the following is true:
69+
70+
- A document is currently available
71+
- No errors occurred
72+
- The context didn't expire
73+
74+
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/cursor.go
75+
:language: go
76+
:dedent:
77+
:start-after: begin cursor try next
78+
:end-before: end cursor try next
79+
80+
Retrieve All Documents
81+
----------------------
82+
83+
To populate an array with all of your query results, use the ``All()``
84+
method:
85+
86+
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/cursor.go
87+
:language: go
88+
:dedent:
89+
:start-after: begin cursor all
90+
:end-before: end cursor all
91+
92+
.. important:: Memory
93+
94+
If the number and size of documents returned by your query exceeds
95+
available application memory, your program will crash. If you except
96+
a large result set, you should :ref:`consume your cursor iteratively
97+
<individual-documents-golang>`.
98+
99+
Close the Cursor
100+
----------------
101+
102+
When your application no longer needs to use a cursor, close the cursor
103+
with the ``Close()`` method. This method frees the resources your cursor
104+
consumes in both the client application and the MongoDB server.
105+
106+
.. literalinclude:: /includes/fundamentals/code-snippets/CRUD/cursor.go
107+
:language: go
108+
:dedent:
109+
:start-after: begin close
110+
:end-before: end close
111+
112+
.. note::
113+
114+
Close the cursor when you :ref:`retrieve documents individually
115+
<individual-documents-golang>` because those methods make a cursor
116+
:manual:`tailable </core/tailable-cursors/>`.
117+
118+
Additional Information
119+
----------------------
120+
121+
For more information on the operations discussed in this guide, see the
122+
following guides:
123+
124+
- :ref:`<retrieve-golang>`
125+
- :ref:`<query_document_golang>`
126+
- :ref:`<bson-golang>`
127+
- :manual:`Tailable Cursors </core/tailable-cursors/>`
128+
129+
.. - Fundamentals > BSON page
130+
131+
API Documentation
132+
~~~~~~~~~~~~~~~~~
133+
134+
For more information on cursors and how to access their elements, see
135+
the following API Documentation:
136+
137+
- `Cursor <{+api+}/mongo#Cursor>`__
138+
- `Cursor.All() <{+api+}/mongo#Cursor.All>`__
139+
- `Cursor.Next() <{+api+}/mongo#Cursor.Next>`__
140+
- `Cursor.TryNext() <{+api+}/mongo#Cursor.TryNext>`__
141+
- `Cursor.Decode() <{+api+}/mongo#Cursor.Decode>`__
142+
- `Cursor.RemainingBatchLength() <{+api+}/mongo#Cursor.RemainingBatchLength>`__
143+
- `Cursor.ID() <{+api+}/mongo#Cursor.ID>`__
144+
- `Cursor.Err() <{+api+}/mongo#Cursor.Err>`__
145+
- `Cursor.Close() <{+api+}/mongo#Cursor.Close>`__

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _retrieve-golang:
2+
13
==============
24
Retrieve Data
35
==============
@@ -51,8 +53,7 @@ The ``Find()`` function expects you to pass a ``Context`` type and a
5153
query filter. The function returns *all* documents that match the filter
5254
as a ``Cursor`` type.
5355

54-
.. To learn how to access data in a cursor, see the :doc:`Cursor
55-
.. </fundamentals/crud/read-operations/cursor>` guide.
56+
To learn how to access data in a cursor, see the :ref:`<cursor-golang>` guide.
5657

5758
Find One Document
5859
~~~~~~~~~~~~~~~~~
@@ -64,6 +65,8 @@ filter as a ``SingleResult`` type.
6465
To learn how to access data in a ``SingleResult`` see the :ref:`BSON
6566
<bson-unmarshalling>` guide.
6667

68+
.. _retrieve-options:
69+
6770
Modify Behavior
6871
~~~~~~~~~~~~~~~
6972

@@ -174,8 +177,7 @@ The function returns the resulting documents in a ``Cursor`` type. If
174177
you omit the :manual:`$match </reference/operator/aggregation/match/#mongodb-pipeline-pipe.-match>`
175178
stage, the pipeline proceeds using all documents in the collection.
176179

177-
.. To learn how to access data in a cursor, see the :doc:`Cursor
178-
.. </fundamentals/crud/read-operations/cursor>` guide.
180+
To learn how to access data in a cursor, see the :ref:`<cursor-golang>` guide.
179181

180182
Modify Behavior
181183
~~~~~~~~~~~~~~~
@@ -271,6 +273,7 @@ For more information about the operations mentioned, see the following
271273
guides:
272274

273275
- :doc:`Specify a Query </fundamentals/crud/query-document>`
276+
- :ref:`<cursor-golang>`
274277
- :doc:`Skip Returned Results </fundamentals/crud/read-operations/skip>`
275278
- :doc:`Sort Results </fundamentals/crud/read-operations/sort>`
276279
- :doc:`Limit the Number of Returned Results </fundamentals/crud/read-operations/limit>`
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"os"
8+
9+
"go.mongodb.org/mongo-driver/bson"
10+
"go.mongodb.org/mongo-driver/mongo"
11+
"go.mongodb.org/mongo-driver/mongo/options"
12+
)
13+
14+
func main() {
15+
var uri string
16+
if uri = os.Getenv("MONGODB_URI"); uri == "" {
17+
log.Fatal("You must set your 'MONGODB_URI' environmental variable. See\n\t https://docs.mongodb.com/drivers/go/current/usage-examples/")
18+
}
19+
20+
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
21+
22+
if err != nil {
23+
panic(err)
24+
}
25+
defer func() {
26+
if err = client.Disconnect(context.TODO()); err != nil {
27+
panic(err)
28+
}
29+
}()
30+
31+
client.Database("tea").Collection("ratings").Drop(context.TODO())
32+
33+
coll := client.Database("tea").Collection("ratings")
34+
docs := []interface{}{
35+
bson.D{{"type", "Masala"}, {"rating", 10}},
36+
bson.D{{"type", "Earl Grey"}, {"rating", 5}},
37+
bson.D{{"type", "Assam"}, {"rating", 7}},
38+
}
39+
40+
result, err := coll.InsertMany(context.TODO(), docs)
41+
if err != nil {
42+
panic(err)
43+
}
44+
fmt.Printf("Number of documents inserted: %d\n", len(result.InsertedIDs))
45+
46+
fmt.Println("Cursor Elements:")
47+
{
48+
opts := options.Find().SetBatchSize(3)
49+
cursor, err := coll.Find(context.TODO(), bson.D{}, opts)
50+
if err != nil {
51+
panic(err)
52+
}
53+
54+
// begin close
55+
defer cursor.Close(context.TODO())
56+
// end close
57+
58+
for cursor.Next(context.TODO()) {
59+
// begin current
60+
fmt.Println(cursor.Current)
61+
// end current
62+
// begin remaining batch length
63+
fmt.Println(cursor.RemainingBatchLength())
64+
// end remaining batch length
65+
// begin id
66+
fmt.Println(cursor.ID())
67+
// end id
68+
// begin err
69+
fmt.Println(cursor.Err())
70+
// end err
71+
}
72+
}
73+
74+
fmt.Println("Cursor.All():")
75+
{
76+
// begin find
77+
cursor, err := coll.Find(context.TODO(), bson.D{})
78+
if err != nil {
79+
panic(err)
80+
}
81+
// end find
82+
83+
defer cursor.Close(context.TODO())
84+
85+
// begin cursor all
86+
var results []bson.D
87+
if err = cursor.All(context.TODO(), &results); err != nil {
88+
panic(err)
89+
}
90+
for _, result := range results {
91+
fmt.Println(result)
92+
}
93+
// end cursor all
94+
}
95+
96+
fmt.Println("Cursor.Next():")
97+
{
98+
cursor, err := coll.Find(context.TODO(), bson.D{})
99+
if err != nil {
100+
panic(err)
101+
}
102+
103+
defer cursor.Close(context.TODO())
104+
105+
// begin cursor next
106+
for cursor.Next(context.TODO()) {
107+
var result bson.D
108+
if err := cursor.Decode(&result); err != nil {
109+
log.Fatal(err)
110+
}
111+
fmt.Println(result)
112+
}
113+
if err := cursor.Err(); err != nil {
114+
log.Fatal(err)
115+
}
116+
// end cursor next
117+
}
118+
119+
fmt.Println("Cursor.TryNext():")
120+
{
121+
cursor, err := coll.Find(context.TODO(), bson.D{})
122+
if err != nil {
123+
panic(err)
124+
}
125+
126+
defer cursor.Close(context.TODO())
127+
128+
// begin cursor try next
129+
for {
130+
if cursor.TryNext(context.TODO()) {
131+
var result bson.D
132+
if err := cursor.Decode(&result); err != nil {
133+
log.Fatal(err)
134+
}
135+
fmt.Println(result)
136+
continue
137+
}
138+
139+
if err := cursor.Err(); err != nil {
140+
log.Fatal(err)
141+
}
142+
if cursor.ID() == 0 {
143+
break
144+
}
145+
}
146+
// end cursor try next
147+
}
148+
}

0 commit comments

Comments
 (0)