@@ -36,134 +36,131 @@ dropped so the actual number of digits may vary.
36
36
Examples
37
37
--------
38
38
39
- This code initializes a ``randomSamples`` collection with 100 documents
40
- that is used in the following examples.
39
+ Generate Random Data Points
40
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
41
41
42
- .. code-block:: javascript
43
-
44
- N = 100
45
- bulk = db.randomSamples.initializeUnorderedBulkOp()
46
- for ( i = 0; i < N; i++) { bulk.insert( {_id: i, random: 0 } ) }
47
- bulk.execute()
48
-
49
-
50
- Usage with Update Queries
51
- ~~~~~~~~~~~~~~~~~~~~~~~~~
52
-
53
- The ``$rand`` operator can be used with update query operations. In
54
- this example :method:`~db.collection.updateMany()` uses the ``$rand``
55
- operator to insert a different random number into each document
56
- in the ``randomSamples`` collection.
42
+ This example models charitable donations. The collection starts with a
43
+ list of donors.
57
44
58
45
.. code-block:: javascript
59
46
60
- db.randomSamples.updateMany(
61
- {},
47
+ db.donors.insertMany(
62
48
[
63
- { $set: { "random": { $rand: {} } } }
49
+ { donorId: 1000, amount: 0, frequency: 1 },
50
+ { donorId: 1001, amount: 0, frequency: 2 },
51
+ { donorId: 1002, amount: 0, frequency: 1 },
52
+ { donorId: 1003, amount: 0, frequency: 2 },
53
+ { donorId: 1004, amount: 0, frequency: 1 }
64
54
]
65
55
)
66
56
67
- We can use : pipeline:`$project` to see the output. The
68
- :pipeline:`$limit` stage halts the pipeline after the third document .
57
+ We use an aggregation pipeline to update each document with a random
58
+ donation amount .
69
59
70
60
.. code-block:: javascript
71
61
72
- db.randomSamples .aggregate(
62
+ db.donors .aggregate(
73
63
[
74
- { $project: {_id: 0, random: 1 } },
75
- { $limit: 3 }
76
- ]
64
+ { $set: { amount: { $multiply: [ { $rand: {} }, 100 ] } } },
65
+ { $set: { amount: { $floor: "$amount" } } },
66
+ { $merge: "donors" }
67
+ ]
77
68
)
78
69
79
- The output shows the random values.
70
+ The first :pipeline:`$set` stage updates the ``amount`` field. An
71
+ initial value between 0 and 1 is generated using ``$rand``. Then
72
+ :expression:`$multiply` scales it upward 100 times.
80
73
81
- .. code-block:: javascript
82
- :copyable: false
83
-
84
- { "random" : 0.8751284485870464 }
85
- { "random" : 0.515147067802108 }
86
- { "random" : 0.3750004525681561 }
74
+ The :expression:`$floor` operator in the second ``$set`` stage removes
75
+ the decimal portion from the ``amount`` to leave an integer value.
87
76
88
- Rounding to Control the Number of Output Digits
89
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
77
+ Finally, :pipeline:`$merge` writes the random value created in the
78
+ previous steps to the ``amount`` field, updating it for each document
79
+ in the ``donors`` collection.
90
80
91
- If you want a shorter random value, consider using :expression:`$round`.
92
- Note that the :pipeline:`$set` stage updates the document, if ``$rand``
93
- is called in a :pipeline:`$project` stage the underlying document is
94
- not modified.
81
+ You can view the results with a projection stage:
95
82
96
83
.. code-block:: javascript
97
84
98
- db.randomSamples .aggregate(
85
+ db.donors .aggregate(
99
86
[
100
- { $match: {} },
101
- { $set: { rounded: { $round: [ "$random", 4 ] } } },
102
- { $out: "randomSamples" }
87
+ { $project: {_id: 0, donorId: 1, amount: 1 } }
103
88
]
104
89
)
105
90
106
- The :pipeline:`$project` stage displays the original and rounded value
107
- for each document.
108
-
109
- .. code-block:: javascript
110
-
111
- db.randomSamples.aggregate(
112
- [
113
- { $project: {_id:0, random:1, rounded: 1 } },
114
- { $limit: 3 }
115
- ]
116
- )
117
-
118
- The update documents look like this:
91
+ The projection shows the scaled amounts are now random values in the
92
+ range from 0 to 99.
119
93
120
94
.. code-block:: javascript
121
95
:copyable: false
122
96
123
- { "random" : 0.8751284485870464, "rounded" : 0.8751 }
124
- { "random" : 0.515147067802108, "rounded" : 0.5151 }
125
- { "random" : 0.3750004525681561, "rounded" : 0.375 }
97
+ { "donorId" : 1000, "amount" : 27 }
98
+ { "donorId" : 1001, "amount" : 10 }
99
+ { "donorId" : 1002, "amount" : 88 }
100
+ { "donorId" : 1003, "amount" : 73 }
101
+ { "donorId" : 1004, "amount" : 5 }
126
102
127
- .. note::
103
+ Select Random Items From a Collection
104
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105
+
106
+ You can use ``$rand`` in an aggregation pipeline to select random
107
+ documents from a collection. Consider a collection of voter records:
128
108
129
- Like ``$rand``, the value returned by the ``$round`` operator does
130
- not include any trailing 0s so the number of digits returned may
131
- vary.
109
+ .. code-block:: javascript
132
110
133
- Selecting Random Items From a Collection
134
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111
+ db.voters.insertMany(
112
+ [
113
+ { name: "Archibald", voterId: 4321, district: 3, registered: true },
114
+ { name: "Beckham", voterId: 4331, district: 3, registered: true },
115
+ { name: "Carolin", voterId: 5321, district: 4, registered: true },
116
+ { name: "Debarge", voterId: 4343, district: 3, registered: false },
117
+ { name: "Eckhard", voterId: 4161, district: 3, registered: false },
118
+ { name: "Faberge", voterId: 4300, district: 1, registered: true },
119
+ { name: "Grimwald", voterId: 4111, district: 3, registered: true },
120
+ { name: "Humphrey", voterId: 2021, district: 3, registered: true },
121
+ { name: "Idelfon", voterId: 1021, district: 4, registered: true },
122
+ { name: "Justo", voterId: 9891, district: 3, registered: false }
123
+ ]
124
+ )
135
125
136
- The ``$rand`` operator can be used in an aggregation pipeline to select
137
- random documents from a collection. In this example we use ``$rand`` to
138
- select about half the documents in the ``randomSamples`` collection.
126
+ Imagine you want to select about half of the voters in District 3 to do
127
+ some polling.
139
128
140
129
.. code-block:: javascript
141
130
142
- db.randomSamples .aggregate(
131
+ db.voters .aggregate(
143
132
[
133
+ { $match: { district: 3 } },
144
134
{ $match: { $expr: { $lt: [0.5, {$rand: {} } ] } } },
145
- { $count: "numMatches" }
135
+ { $project: { _id: 0, name: 1, registered: 1 } }
146
136
]
147
137
)
148
138
149
- There are 100 documents in ``randomSamples``. Running the sample code 5
150
- times produces the following output which approaches the expected value
151
- of 50 matches in a collection this size.
152
-
139
+ The first pipeline stage matches all documents where the voter is from
140
+ district 3.
141
+
142
+ The second :pipeline:`$match` stage uses ``$rand`` in a match
143
+ expression to further refine the selection. For each document,
144
+ ``$rand`` generates a value between 0 and 1. The threshhold of ``0.5``
145
+ in the less than :expression:`($lt)<$lt>` comparison means that
146
+ :query:`$expr` will be true for about half the documents.
147
+
148
+ In the :pipeline:`$project` stage the selected documents are filtered
149
+ to return the ``name`` and ``registered`` fields. There are 7 voters in
150
+ District 3, running the code selects about half of them.
151
+
153
152
.. code-block:: javascript
154
153
:copyable: false
155
154
156
- { "numMatches" : 49 }
157
- { "numMatches" : 52 }
158
- { "numMatches" : 54 }
159
- { "numMatches" : 48 }
160
- { "numMatches" : 59 }
155
+ { "name" : "Archibald", "registered" : true }
156
+ { "name" : "Debarge", "registered" : false }
157
+ { "name" : "Humphrey", "registered" : true }
161
158
162
159
.. note::
163
160
164
- This example shows that the number of documents selected is
165
- different each time. If you need to select an exact number of
166
- documents, consider using :pipeline:`$sample` instead of ``$rand``.
161
+ The number of documents selected is different each time. If you need
162
+ to select an exact number of documents, consider using
163
+ :pipeline:`$sample` instead of ``$rand``.
167
164
168
165
.. seealso::
169
166
0 commit comments