@@ -36,134 +36,131 @@ dropped so the actual number of digits may vary.
3636Examples
3737--------
3838
39- This code initializes a ``randomSamples`` collection with 100 documents
40- that is used in the following examples.
39+ Generate Random Data Points
40+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4141
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.
5744
5845.. code-block:: javascript
5946
60- db.randomSamples.updateMany(
61- {},
47+ db.donors.insertMany(
6248 [
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 }
6454 ]
6555 )
6656
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 .
6959
7060.. code-block:: javascript
7161
72- db.randomSamples .aggregate(
62+ db.donors .aggregate(
7363 [
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+ ]
7768 )
7869
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.
8073
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.
8776
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.
9080
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:
9582
9683.. code-block:: javascript
9784
98- db.randomSamples .aggregate(
85+ db.donors .aggregate(
9986 [
100- { $match: {} },
101- { $set: { rounded: { $round: [ "$random", 4 ] } } },
102- { $out: "randomSamples" }
87+ { $project: {_id: 0, donorId: 1, amount: 1 } }
10388 ]
10489 )
10590
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.
11993
12094.. code-block:: javascript
12195 :copyable: false
12296
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 }
126102
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:
128108
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
132110
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+ )
135125
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.
139128
140129.. code-block:: javascript
141130
142- db.randomSamples .aggregate(
131+ db.voters .aggregate(
143132 [
133+ { $match: { district: 3 } },
144134 { $match: { $expr: { $lt: [0.5, {$rand: {} } ] } } },
145- { $count: "numMatches" }
135+ { $project: { _id: 0, name: 1, registered: 1 } }
146136 ]
147137 )
148138
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+
153152.. code-block:: javascript
154153 :copyable: false
155154
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 }
161158
162159.. note::
163160
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``.
167164
168165.. seealso::
169166
0 commit comments