Skip to content

Commit d0851a0

Browse files
(DOCS-14913): locf operator (#107)
* (DOCS-14913): locf operator * updates per review feedback * Add context to example * more tweaks * adjustments * formatting fix * grammar * updates per second round of review * tweaks * typo fix * line break * (DOCS-14913): Address review comments * change word * updates per review * tweaks * remove extra digit from hour field * fix example output * adjust example format * fix release notes after rebase
1 parent fcb8b65 commit d0851a0

File tree

6 files changed

+303
-2
lines changed

6 files changed

+303
-2
lines changed

source/includes/extracts-agg-operators.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,6 @@ content: |
511511
expressions. If the two values are a date and a number,
512512
specify the date argument first as it is not meaningful to
513513
subtract a date from a number.
514-
515514
---
516515
ref: agg-operators-miscellaneous
517516
content: |
@@ -1261,6 +1260,14 @@ content: |
12611260
12621261
Available in :pipeline:`$setWindowFields` stage.
12631262
1263+
* - :group:`$locf`
1264+
1265+
- .. include:: /includes/fact-locf-description.rst
1266+
1267+
Available in :pipeline:`$setWindowFields` stage.
1268+
1269+
.. versionadded:: 5.2
1270+
12641271
* - :group:`$max`
12651272
12661273
- Returns the maximum value that results from applying an
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Last observation carried forward. Sets values for ``null`` and missing
2+
fields in a :ref:`window <setWindowFields-window>` to the last non-null
3+
value for the field.

source/includes/setWindowFields-operators.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ These operators can be used with the :pipeline:`$setWindowFields` stage:
88
:group:`$max`, :group:`$min`, :group:`$push`, :group:`$stdDevSamp`,
99
:group:`$stdDevPop`, and :group:`$sum`.
1010

11+
.. _setWindowFields-gap-filling-operators:
12+
13+
- Gap filling operators: :group:`$locf`.
14+
1115
.. _setWindowFields-order-operators:
1216

1317
- Order operators: :group:`$first`, :group:`$last`, and :group:`$shift`.
1418

1519
.. _setWindowFields-rank-operators:
1620

1721
- Rank operators: :group:`$denseRank`, :group:`$documentNumber`, and
18-
:group:`$rank`.
22+
:group:`$rank`.

source/reference/operator/aggregation.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,12 @@ Alphabetical Listing of Expression Operators
645645

646646
- Calculates the natural log of a number.
647647

648+
* - :group:`$locf`
649+
650+
- .. include:: /includes/fact-locf-description.rst
651+
652+
.. versionadded:: 5.2
653+
648654
* - :expression:`$log`
649655

650656
- Calculates the log of a number in the specified base.
@@ -1227,6 +1233,7 @@ Alphabetical Listing of Expression Operators
12271233
/reference/operator/aggregation/let
12281234
/reference/operator/aggregation/literal
12291235
/reference/operator/aggregation/ln
1236+
/reference/operator/aggregation/locf
12301237
/reference/operator/aggregation/log
12311238
/reference/operator/aggregation/log10
12321239
/reference/operator/aggregation/lt
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
===================
2+
$locf (aggregation)
3+
===================
4+
5+
.. default-domain:: mongodb
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 1
11+
:class: singlecol
12+
13+
Definition
14+
----------
15+
16+
.. group:: $locf
17+
18+
.. versionadded:: 5.2
19+
20+
.. include:: /includes/fact-locf-description.rst
21+
22+
:group:`$locf` is only available in the :pipeline:`$setWindowFields`
23+
stage.
24+
25+
Syntax
26+
------
27+
28+
The :group:`$locf` expression has this syntax:
29+
30+
.. code-block:: none
31+
32+
{ $locf: <expression> }
33+
34+
For more information on expressions, see
35+
:ref:`aggregation-expressions`.
36+
37+
Behavior
38+
--------
39+
40+
If a field being filled contains both ``null`` and non-null values,
41+
:group:`$locf` sets the ``null`` and missing values to the field's
42+
last known non-null value according to the sort order specified in
43+
:pipeline:`$setWindowFields`.
44+
45+
``null`` and missing field values that appear before non-null values
46+
in the sort order remain ``null``.
47+
48+
If a field being filled contains only ``null`` or missing values in a
49+
:ref:`partition <setWindowFields-partitionBy>`, :group:`$locf` sets the
50+
field value to ``null`` for that partition.
51+
52+
Example
53+
-------
54+
55+
Create a ``stock`` collection that contains data for two different
56+
company stocks trading in the financial market. The collection contains
57+
the following properties of the stocks, recorded at hourly intervals:
58+
59+
.. list-table::
60+
:header-rows: 1
61+
:stub-columns: 1
62+
:widths: 10 10 20
63+
64+
* - Field
65+
- Type
66+
- Description
67+
68+
* - ``time``
69+
- Date
70+
- Time when the stock ``price`` and ``volume`` were observed.
71+
72+
* - ``company``
73+
- String
74+
- Name of the company.
75+
76+
* - ``price``
77+
- Decimal
78+
- Price of the stock at the ``time`` observed.
79+
80+
* - ``volume``
81+
- Integer
82+
- Number of shares traded over one day.
83+
84+
Not all documents in the dataset contain all of the previous fields.
85+
86+
.. code-block:: javascript
87+
88+
db.stock.insertMany( [
89+
{
90+
time: "2021-03-08T09:00:00.000Z",
91+
company: "CompanyA",
92+
price: 500,
93+
volume: 200000
94+
},
95+
{
96+
time: "2021-03-08T09:00:00.000Z",
97+
company: "CompanyB",
98+
price: 20,
99+
volume: 100000
100+
},
101+
{
102+
time: "2021-03-08T10:00:00.000Z",
103+
company: "CompanyA",
104+
price: 490,
105+
volume: 205000
106+
},
107+
{
108+
time: "2021-03-08T10:00:00.000Z",
109+
company: "CompanyB",
110+
price: 22,
111+
volume: 105000
112+
},
113+
{
114+
time: "2021-03-08T11:00:00.000Z",
115+
company: "CompanyA"
116+
},
117+
{
118+
time: "2021-03-08T11:00:00.000Z",
119+
company: "CompanyB",
120+
price: 24,
121+
volume: null
122+
},
123+
{
124+
time: "2021-03-08T12:00:00.000Z",
125+
company: "CompanyA",
126+
price: 510,
127+
volume: 220000
128+
},
129+
{
130+
time: "2021-03-08T12:00:00.000Z",
131+
company: "CompanyB"
132+
},
133+
{
134+
time: "2021-03-08T13:00:00.000Z",
135+
company: "CompanyA",
136+
price: 505,
137+
volume: 225000
138+
},
139+
{
140+
time: "2021-03-08T13:00:00.000Z",
141+
company: "CompanyB",
142+
price: 28,
143+
volume: 120000
144+
}
145+
] )
146+
147+
The following example uses the :group:`$locf` operator to set ``null``
148+
and missing fields to the values from the last document with a non-null
149+
value in the corresponding partition:
150+
151+
.. code-block:: javascript
152+
:emphasize-lines: 7-8
153+
154+
db.stock.aggregate( [
155+
{
156+
$setWindowFields: {
157+
partitionBy: "$company",
158+
sortBy: { time: 1 },
159+
output: {
160+
price: { $locf: "$price" },
161+
volume: { $locf: "$volume" }
162+
}
163+
}
164+
}
165+
] )
166+
167+
In the example:
168+
169+
- ``partitionBy: "$company"`` :ref:`partitions
170+
<setWindowFields-partitionBy>` the documents by ``company``. There
171+
are partitions for ``CompanyA`` and ``CompanyB``.
172+
173+
- ``sortBy: { time: 1 }`` :ref:`sorts
174+
<setWindowFields-sortBy>` the documents in each partition by
175+
``time`` in ascending order (``1``), so the earliest
176+
``time`` is first.
177+
178+
- For documents where ``price`` or ``volume`` is ``null`` or missing,
179+
the :group:`$locf` operator sets the missing field to the previous
180+
value for that field in the partition.
181+
182+
Example output:
183+
184+
.. code-block:: javascript
185+
:copyable: false
186+
187+
[
188+
{
189+
_id: ObjectId("61b11166b412e1948a407dc6"),
190+
time: '2021-03-08T09:00:00.000Z',
191+
company: 'CompanyA',
192+
price: 500,
193+
volume: 200000
194+
},
195+
{
196+
_id: ObjectId("61b11166b412e1948a407dc8"),
197+
time: '2021-03-08T10:00:00.000Z',
198+
company: 'CompanyA',
199+
price: 490,
200+
volume: 205000
201+
},
202+
{
203+
_id: ObjectId("61b11166b412e1948a407dca"),
204+
time: '2021-03-08T11:00:00.000Z',
205+
company: 'CompanyA',
206+
price: 490,
207+
volume: 205000
208+
},
209+
{
210+
_id: ObjectId("61b11166b412e1948a407dcc"),
211+
time: '2021-03-08T12:00:00.000Z',
212+
company: 'CompanyA',
213+
price: 510,
214+
volume: 220000
215+
},
216+
{
217+
_id: ObjectId("61b11166b412e1948a407dce"),
218+
time: '2021-03-08T13:00:00.000Z',
219+
company: 'CompanyA',
220+
price: 505,
221+
volume: 225000
222+
},
223+
{
224+
_id: ObjectId("61b11166b412e1948a407dc7"),
225+
time: '2021-03-08T09:00:00.000Z',
226+
company: 'CompanyB',
227+
price: 20,
228+
volume: 100000
229+
},
230+
{
231+
_id: ObjectId("61b11166b412e1948a407dc9"),
232+
time: '2021-03-08T10:00:00.000Z',
233+
company: 'CompanyB',
234+
price: 22,
235+
volume: 105000
236+
},
237+
{
238+
_id: ObjectId("61b11166b412e1948a407dcb"),
239+
time: '2021-03-08T11:00:00.000Z',
240+
company: 'CompanyB',
241+
price: 24,
242+
volume: 105000
243+
},
244+
{
245+
_id: ObjectId("61b11166b412e1948a407dcd"),
246+
time: '2021-03-08T12:00:00.000Z',
247+
company: 'CompanyB',
248+
price: 24,
249+
volume: 105000
250+
},
251+
{
252+
_id: ObjectId("61b11166b412e1948a407dcf"),
253+
time: '2021-03-08T13:00:00.000Z',
254+
company: 'CompanyB',
255+
price: 28,
256+
volume: 120000
257+
}
258+
]

source/release-notes/5.2.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,28 @@ Release Notes for MongoDB 5.2
1212

1313
.. include:: /includes/in-dev.rst
1414

15+
.. _5.2-rel-notes-aggregation:
16+
17+
Aggregation
18+
-----------
19+
20+
.. _5.2-rel-notes-new-agg-operators:
21+
22+
New Aggregation Operators
23+
~~~~~~~~~~~~~~~~~~~~~~~~~
24+
25+
MongoDB 5.2 introduces the following aggregation operators:
26+
27+
.. list-table::
28+
:header-rows: 1
29+
:widths: 20 80
30+
31+
* - Operator
32+
- Description
33+
34+
* - :group:`$locf`
35+
- .. include:: /includes/fact-locf-description.rst
36+
1537
.. _5.2-rel-notes-general:
1638

1739
General Improvements

0 commit comments

Comments
 (0)