@@ -48,8 +48,8 @@ fields:
4848Use Secondary Indexes to Improve Sort Performance
4949-------------------------------------------------
5050
51- Sort operations on the ``timeField`` and ``metaField`` can use secondary
52- indexes on those fields to improve performance.
51+ Create secondary indexes on the ``timeField`` and ``metaField`` fields to
52+ improve sort performance.
5353
5454For example, the following ``sensorData`` collection contains
5555temperature readings:
@@ -101,6 +101,74 @@ The ``winningPlan.queryPlan.inputStage.stage`` is ``IXSCAN``, which
101101indicates that the index was used. For more information on explain plan
102102output, see :ref:`explain-results`.
103103
104+ "Last Point" Queries on Time Series Collections
105+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106+
107+ A "last point" query fetches the latest measurement for each unique metadata
108+ value. For example, you may want to get the latest temperature reading from all
109+ sensors. Improve performance on last point queries by creating any of the
110+ following indexes:
111+
112+ .. code-block:: javascript
113+
114+ { "metadata.sensorId": 1, "timestamp": 1 }
115+ { "metadata.sensorId": 1, "timestamp": -1 }
116+ { "metadata.sensorId": -1, "timestamp": 1 }
117+ { "metadata.sensorId": -1, "timestamp": -1 }
118+
119+ .. note::
120+
121+ Last point queries are most performant when they use the :ref:`DISTINCT_SCAN
122+ optimization <explain-results>`. This optimization is only available when an
123+ index on ``timeField`` is descending.
124+
125+ The following command creates a compound secondary index on ``metaField``
126+ (ascending) and ``timeField`` (descending):
127+
128+ .. code-block:: javascript
129+
130+ db.sensorData.createIndex( { "metadata.sensorId": 1, "timestamp": -1 } )
131+
132+ The following last point query example uses the descending ``timeField``
133+ compound secondary index created above:
134+
135+ .. code-block:: javascript
136+
137+ db.sensorData.aggregate( [
138+ {
139+ $sort: { "metadata.sensorId": 1, "timestamp": -1 }
140+ },
141+ {
142+ $group: {
143+ _id: "$metadata.sensorId",
144+ ts: { $first: "$timestamp" },
145+ temperatureF: { $first: "$currentConditions.tempF" }
146+ }
147+ }
148+ ] )
149+
150+ To confirm that the last point query used the secondary index, run the operation
151+ again using ``.explain("executionStats")``:
152+
153+ .. code-block:: javascript
154+
155+ db.getCollection('sensorData').explain("executionStats").aggregate( [
156+ {
157+ $sort: { "metadata.sensorId": 1, "timestamp": -1 }
158+ },
159+ {
160+ $group: {
161+ _id: "$metadata.sensorId",
162+ ts: {$first: "$timestamp"},
163+ temperatureF: {$first: "$currentConditions.tempF" }
164+ }
165+ }
166+ ] )
167+
168+ The ``winningPlan.queryPlan.inputStage.stage`` is ``DISTINCT_SCAN``, which
169+ indicates that the index was used. For more information on the explain plan
170+ output, see :ref:`explain-results`.
171+
104172Specify Index Hints for Time Series Collections
105173~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106174
0 commit comments