@@ -17,103 +17,155 @@ Definition
17
17
18
18
.. versionadded:: 4.4.2
19
19
20
- The :expression:`$rand` operator generates a random value between 0
21
- and 1 each time it is called.
20
+ Returns a random float between 0 and 1 each time it is called.
21
+
22
+ :expression:`$rand` has the following syntax:
23
+
24
+ .. code-block:: javascript
25
+
26
+ { $rand: {} }
27
+
28
+ The :expression:`$rand` operator doesn't take any arguments.
29
+
30
+ Behavior
31
+ --------
32
+ Each time ``$rand`` is called it will return a floating point value
33
+ that has up to 17 digits after the decimal point. Trailing 0s are
34
+ dropped so the actual number of digits may vary.
22
35
23
36
Examples
24
37
--------
25
38
26
- This code creates a small collection with 100 documents which we will
27
- use in these examples. (Increase the value of ``N`` if you want to
28
- experiment with larger data sets).
29
-
39
+ This code initializes a ``randomSamples`` collection with 100 documents
40
+ that is used in the following examples.
41
+
30
42
.. code-block:: javascript
31
43
32
44
N = 100
33
- bulk = db.collection .initializeUnorderedBulkOp()
34
- for (i = 0; i < N; i++) { bulk.insert({_id: i, r : 0} ) }
45
+ bulk = db.randomSamples .initializeUnorderedBulkOp()
46
+ for ( i = 0; i < N; i++) { bulk.insert( {_id: i, random : 0 } ) }
35
47
bulk.execute()
36
48
37
- Consider the following examples:
38
49
39
- The ``$rand`` operator can be used in a pipeline to select random
40
- documents from a collection. In this example we use the same database
41
- and ``$rand`` to select about half the documents.
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
57
43
58
.. code-block:: javascript
44
59
45
- db.collection.aggregate(
46
- [
47
- { $match:
48
- {
49
- $expr:
50
- {
51
- $lt: [0.5, {$rand: {} } ]
52
- }
53
- }
54
- },
55
- {
56
- $count: "numMatches"
57
- }
58
- ]
59
- )
60
+ db.randomSamples.updateMany(
61
+ {},
62
+ [
63
+ { $set: { "random": { $rand: {} } } }
64
+ ]
65
+ )
66
+
67
+ We can use :pipeline:`$project` to see the output. The
68
+ :pipeline:`$limit` stage halts the pipeline after the third document.
60
69
61
70
.. code-block:: javascript
62
- :copyable: false
63
71
64
- // Output of 5 runs on the sample collection
65
- { "numMatches" : 49 }
66
- { "numMatches" : 52 }
67
- { "numMatches" : 54 }
68
- { "numMatches" : 48 }
69
- { "numMatches" : 59 }
72
+ db.randomSamples.aggregate(
73
+ [
74
+ { $project: {_id: 0, random: 1 } },
75
+ { $limit: 3 }
76
+ ]
77
+ )
70
78
71
- .. note::
79
+ The output shows the random values.
80
+
81
+ .. code-block:: javascript
82
+ :copyable: false
83
+
84
+ { "random" : 0.8751284485870464 }
85
+ { "random" : 0.515147067802108 }
86
+ { "random" : 0.3750004525681561 }
72
87
73
- This example returns different results each time. Smaller datasets
74
- show more variability in repeated runs. The number of documents
75
- selected each time approaches the expected value (in this case 50%)
76
- as the collection size grows.
88
+ Rounding to Control the Number of Output Digits
89
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
77
90
78
- Update operations accept aggregation pipelines. In this example the
79
- ``$rand`` operator is used to insert a different random number into each
80
- document in a collection.
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
95
82
96
.. code-block:: javascript
83
97
84
- db.collection.updateMany({}, [
85
- {
86
- $set:
87
- {
88
- "r":
89
- {
90
- $rand: {}
91
- }
92
- }
93
- }
94
- ]
95
- )
96
-
97
- This is brief excerpt showing the results of the update:
98
+ db.randomSamples.aggregate(
99
+ [
100
+ { $match: {} },
101
+ { $set: { rounded: { $round: [ "$random", 4 ] } } },
102
+ { $out: "randomSamples" }
103
+ ]
104
+ )
105
+
106
+ The :pipeline:`$project` stage displays the original and rounded value
107
+ for each document.
98
108
99
109
.. code-block:: javascript
100
- :copyable: false
101
-
102
- db.collection.aggregate(
103
- [
104
- {
105
- $project: {_id:0, r:1 }
106
- }
107
- ]
108
- )
109
-
110
- { "r" : 0.9141450086748962 }
111
- { "r" : 0.151174715006409 }
112
- { "r" : 0.4311952154820518 }
113
- { "r" : 0.08106914853292181 }
114
- ...
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:
119
+
120
+ .. code-block:: javascript
121
+ :copyable: false
122
+
123
+ { "random" : 0.8751284485870464, "rounded" : 0.8751 }
124
+ { "random" : 0.515147067802108, "rounded" : 0.5151 }
125
+ { "random" : 0.3750004525681561, "rounded" : 0.375 }
126
+
127
+ .. note::
128
+
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.
132
+
133
+ Selecting Random Items From a Collection
134
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
135
+
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.
139
+
140
+ .. code-block:: javascript
141
+
142
+ db.randomSamples.aggregate(
143
+ [
144
+ { $match: { $expr: { $lt: [0.5, {$rand: {} } ] } } },
145
+ { $count: "numMatches" }
146
+ ]
147
+ )
148
+
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
+
153
+ .. code-block:: javascript
154
+ :copyable: false
155
+
156
+ { "numMatches" : 49 }
157
+ { "numMatches" : 52 }
158
+ { "numMatches" : 54 }
159
+ { "numMatches" : 48 }
160
+ { "numMatches" : 59 }
161
+
162
+ .. note::
163
+
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``.
115
167
116
168
.. seealso::
117
169
118
- :expression :`$let `, :query :`$rand`.
170
+ :query :`$rand (query) <$rand> `, :pipeline :`$sample`, :expression:`$round`
119
171
0 commit comments