@@ -11,3 +11,332 @@ Sorts Builders
1111 :class: singlecol
1212
1313.. _sorts-builders:
14+
15+ Overview
16+ --------
17+
18+ In this guide, we show you how to specify **sort criteria** for your
19+ queries using **builders**.
20+
21+ Sort criteria are the rules MongoDB uses to sort your data. Some
22+ examples of sort criteria are:
23+
24+ * Smallest number to largest number
25+ * Earliest time of day to latest time of day
26+ * Alphabetical order by first name
27+
28+ Builders are classes provided by the MongoDB Java driver that help you construct
29+ :java-docs:`Bson <apidocs/bson/org/bson/conversions/Bson.html>` objects.
30+ To learn more, see our :doc:`guide on builders </fundamentals/builders/>`.
31+
32+ You should read this guide if you would like to:
33+
34+ * Use builders to specify sort criteria for your queries.
35+ * Perform ascending sorts and descending sorts.
36+ * Combine sort criteria.
37+ * Sort on the text score of a
38+ :manual:`text search </core/text-search-operators/>`.
39+
40+ If you want to learn the fundamentals of sorting in the MongoDB Java
41+ driver, consider reading our
42+ :doc:`guide on sorting </fundamentals/crud/read-operations/sort/>`.
43+
44+ The Sorts Class
45+ ---------------
46+
47+ The :java-docs:`Sorts </apidocs/mongodb-driver-core/com/mongodb/client/model/Sorts.html>`
48+ class is a builder that provides static factory methods for all sort criteria
49+ operators supported by MongoDB. These methods return a
50+ :java-docs:`Bson </apidocs/bson/org/bson/conversions/Bson.html>`
51+ object that you can pass to the
52+ :java-docs:`sort() </apidocs/mongodb-driver-sync/com/mongodb/client/FindIterable.html#sort(org.bson.conversions.Bson)>`
53+ method of a ``FindIterable`` instance or to
54+ :java-docs:`Aggregates.sort() </apidocs/mongodb-driver-core/com/mongodb/client/model/Aggregates.html#sort(org.bson.conversions.Bson)>`.
55+ If you want to learn more about ``Aggregates``, see our
56+ :doc:`guide on the Aggregates builder </fundamentals/builders/aggregates>`.
57+
58+
59+ .. _sorts-builders-sort-example:
60+
61+ The following examples show you how to use the methods
62+ provided by the ``Sorts`` class to sort your queries. The examples use a
63+ sample collection, ``sort_example``, that contains the following documents:
64+
65+ .. code-block:: json
66+
67+ {"_id": 1, "letter": "c", "food": "coffee with milk"}
68+ {"_id": 3, "letter": "a", "food": "maple syrup"}
69+ {"_id": 4, "letter": "b", "food": "coffee with sugar"}
70+ {"_id": 5, "letter": "a", "food": "milk and cookies"}
71+ {"_id": 2, "letter": "a", "food": "donuts and coffee"}
72+ {"_id": 6, "letter": "c", "food": "maple donut"}
73+
74+
75+ Sorting Direction
76+ -----------------
77+
78+ The ``Sorts`` class provides methods for specifying the direction of your sort.
79+ The direction of your sort can either be **ascending** or **descending**.
80+ An ascending sort orders your results from smallest to largest. A
81+ descending sort orders your results from largest to smallest.
82+
83+ Here are some examples of data sorted in ascending order:
84+
85+ * Numbers: 1, 2, 3, 43, 43, 55, 120
86+ * Dates: 1990-03-10, 1995-01-01, 2005-10-30, 2005-12-21
87+ * Words (ASCII): Banana, Dill, carrot, cucumber, hummus
88+
89+ Here are some examples of data sorted in descending order:
90+
91+ * Numbers: 100, 30, 12, 12, 9, 3, 1
92+ * Dates: 2020-01-01, 1998-12-11, 1998-12-10, 1975-07-22
93+ * Words (reverse ASCII): pear, grapes, apple, Cheese
94+
95+ The following subsections show how to specify these sorts using
96+ the ``Sorts`` class.
97+
98+ Ascending
99+ ~~~~~~~~~
100+
101+ To specify an ascending sort, use the ``Sorts.ascending()`` static
102+ factory method. Pass ``Sorts.ascending()``
103+ the name of the field you need to sort on.
104+
105+ The ``ascending()`` method can be used as follows:
106+
107+ .. code-block:: java
108+
109+ import static com.mongodb.client.model.Sorts.ascending;
110+
111+ // <MongoCollection setup code here>
112+
113+ collection.find().sort(ascending("<field name>"));
114+
115+ The above ``sort()`` method returns a
116+ :java-docs:`FindIterable </apidocs/mongodb-driver-sync/com/mongodb/client/FindIterable.html>`
117+ object containing the documents in your collection, sorted from smallest
118+ to largest on the specified field name.
119+
120+ In the following code example, we use the ``ascending()`` method to sort the
121+ :ref:`sort_example collection <sorts-builders-sort-example>`
122+ by the ``_id`` field:
123+
124+ .. code-block:: java
125+
126+ import static com.mongodb.client.model.Sorts.ascending;
127+
128+ // <MongoCollection setup code here>
129+
130+ Bson idSort = ascending("_id");
131+ List<Document> results = new ArrayList<>();
132+ collection.find().sort(idSort).into(results);
133+ for (Document result : results) {
134+ System.out.println(result.toJson());
135+ }
136+
137+ The output of the code example above should look something like this:
138+
139+ .. code-block:: json
140+
141+ {"_id": 1, "letter": "c", "food": "coffee with milk"}
142+ {"_id": 2, "letter": "a", "food": "donuts and coffee"}
143+ {"_id": 3, "letter": "a", "food": "maple syrup"}
144+ ...
145+
146+ Descending
147+ ~~~~~~~~~~
148+
149+ To specify a descending sort, use the ``Sorts.descending()`` static factory
150+ method. Pass ``Sorts.descending()`` the name of the field you need to sort on.
151+
152+ The following code snippet shows how to specify a descending sort on the
153+ ``_id`` field:
154+
155+ .. code-block:: java
156+
157+ import static com.mongodb.client.model.Sorts.descending;
158+
159+ // <MongoCollection setup code here>
160+
161+ collection.find().sort(descending("_id"));
162+
163+
164+ The code snippet above returns the documents in the
165+ :ref:`sort_example collection <sorts-builders-sort-example>`
166+ in the following order:
167+
168+ .. code-block:: json
169+
170+ {"_id": 6, "letter": "c", "food": "maple donut"}
171+ {"_id": 5, "letter": "a", "food": "milk and cookies"}
172+ {"_id": 4, "letter": "b", "food": "coffee with sugar"}
173+ ...
174+
175+ Handling Ties
176+ ~~~~~~~~~~~~~
177+
178+ A tie occurs when two or more documents have a field with identical values.
179+ MongoDB does not guarantee sort order in the event of ties. For example, suppose
180+ we encounter a tie when applying a sort to the
181+ :ref:`sort_example collection <sorts-builders-sort-example>` using the following
182+ code:
183+
184+ .. code-block:: java
185+
186+ import static com.mongodb.client.model.Sorts.ascending;
187+
188+ // <MongoCollection setup code here>
189+
190+ collection.find().sort(ascending("letter"));
191+
192+ Since multiple documents contain "a" on the field we are sorting on, the first
193+ document returned could be any of the following documents:
194+
195+ .. code-block:: json
196+
197+ {"_id": 3, "letter": "a", "food": "maple syrup"}
198+ {"_id": 5, "letter": "a", "food": "milk and cookies"}
199+ {"_id": 2, "letter": "a", "food": "donuts and coffee"}
200+
201+ If you need guaranteed sort order for documents that
202+ have fields with identical values, you can specify additional fields to sort
203+ on in the event of a tie.
204+
205+ We can specify an ascending sort on the ``letter`` field followed by the
206+ ``_id`` field as follows:
207+
208+ .. code-block:: java
209+
210+ import static com.mongodb.client.model.Sorts.ascending;
211+
212+ // <MongoCollection setup code here>
213+
214+ collection.find().sort(ascending("letter", "_id"));
215+
216+ The code snippet above returns the documents in the
217+ :ref:`sort_example collection <sorts-builders-sort-example>`
218+ in the following order:
219+
220+ .. code-block:: json
221+
222+ {"_id": 2, "letter": "a", "food": "donuts and coffee"}
223+ {"_id": 3, "letter": "a", "food": "maple syrup"}
224+ {"_id": 5, "letter": "a", "food": "milk and cookies"}
225+ {"_id": 4, "letter": "b", "food": "coffee with sugar"}
226+ {"_id": 1, "letter": "c", "food": "coffee with milk"}
227+ {"_id": 6, "letter": "c", "food": "maple donut"}
228+
229+ Combining Sort Criteria
230+ -----------------------
231+
232+ To combine sort criteria, use the ``Sorts.orderBy()`` static factory
233+ method. The ``orderBy()`` method builds sort criteria that apply passed
234+ in sort criteria from left to right in the event of ties.
235+
236+ In the following code snippet, we use the ``orderBy()`` method to combine a
237+ descending sort on the ``letter`` field with an ascending sort on the
238+ ``_id`` field.
239+
240+ .. code-block:: java
241+
242+ import static com.mongodb.client.model.Sorts.orderBy;
243+ import static com.mongodb.client.model.Sorts.ascending;
244+ import static com.mongodb.client.model.Sorts.descending;
245+
246+ // <MongoCollection setup code here>
247+
248+ Bson orderBySort = orderBy(descending("letter"), ascending("_id"));
249+ collection.find().sort(orderBySort);
250+
251+ The code snippet above returns the documents in the
252+ :ref:`sort_example collection <sorts-builders-sort-example>`
253+ in the following order:
254+
255+ .. code-block:: json
256+
257+ {"_id": 1, "letter": "c", "food": "coffee with milk"}
258+ {"_id": 6, "letter": "c", "food": "maple donut"}
259+ {"_id": 4, "letter": "b", "food": "coffee with sugar"}
260+ {"_id": 2, "letter": "a", "food": "donuts and coffee"}
261+ {"_id": 3, "letter": "a", "food": "maple syrup"}
262+ {"_id": 5, "letter": "a", "food": "milk and cookies"}
263+
264+ Text Search
265+ -----------
266+
267+ You can specify the order of the results of a
268+ :manual:`text search </text-search/>` by how closely they match your
269+ search string. Each of your search results has a
270+ :manual:`text score </reference/operator/aggregation/meta/#exp._S_meta>`, a
271+ numerical value indicating how well that result matches your search.
272+ Use the ``Sorts.metaTextScore()`` static factory method to build your sort
273+ criteria to sort by the text score.
274+
275+ .. warning:: Make Sure to Create a Text Index
276+
277+ You need a :manual:`text index </core/index-text/>` on your collection to perform a text search. See the server manual documentation for more
278+ information on how to
279+ :manual:`create a text index </core/index-text/#create-text-index>`.
280+
281+ In the following code example, we show how you can use the
282+ ``Sorts.metaTextScore()`` method to sort the results of a text
283+ search on the :ref:`sort_example collection <sorts-builders-sort-example>`.
284+ The code example uses the :doc:`Filters </fundamentals/builders/filters>`,
285+ :doc:`Indexes </fundamentals/builders/indexes>`, and
286+ :doc:`Projections </fundamentals/builders/projections>` builders.
287+ The code example performs the following actions:
288+
289+ #. Creates a text index for your
290+ :ref:`sort_example collection <sorts-builders-sort-example>`
291+ on the ``food`` field.
292+ #. Runs your text search for the phrase "maple donut".
293+ #. Projects text scores into your query results as the
294+ ``score`` field. This projection is optional if your MongoDB instance is
295+ running MongoDB 4.4 or later.
296+ #. Sorts your results by text score (best match first).
297+
298+ .. code-block:: java
299+
300+ import com.mongodb.client.model.Sorts;
301+ import com.mongodb.client.model.Projections;
302+ import com.mongodb.client.model.Filters;
303+ import com.mongodb.client.model.Indexes;
304+
305+ // <MongoCollection setup code here>
306+
307+ collection.createIndex(Indexes.text("food"));
308+ Bson metaTextScoreSort = Sorts.metaTextScore("score");
309+ Bson metaTextScoreProj = Projections.metaTextScore("score");
310+ String searchTerm = "maple donut";
311+ Bson searchQuery = Filters.text(searchTerm);
312+ collection.find(searchQuery)
313+ .projection(metaTextScoreProj)
314+ .sort(metaTextScoreSort)
315+ .into(results);
316+ for (Document result : results) {
317+ System.out.println(result.toJson());
318+ }
319+
320+ The output of the code example above should look something like this:
321+
322+ .. code-block:: json
323+
324+ {"_id": 6, "letter": "c", "food": "maple donut", "score": 1.5}
325+ {"_id": 2, "letter": "a", "food": "donuts and coffee", "score": 0.75}
326+ {"_id": 3, "letter": "a", "food": "maple syrup", "score": 0.75}
327+
328+ .. note:: MongoDB 4.4 or later ``$meta`` Behavior
329+
330+ When using MongoDB 4.4 or later, projecting ``Projections.metaTextScore()``
331+ into your ``FindIterable`` instance is not necessary to sort on the text
332+ score. In addition, MongoDB 4.4 or later disregards the field name you specify
333+ in a ``$meta`` text score aggregation operation used in a sort. This means
334+ that the field name argument you pass to ``Sorts.metaTextScore()`` is ignored
335+ in MongoDB 4.4 or later.
336+
337+ For more information, see the
338+ :java-docs:`Sorts class API documentation </apidocs/mongodb-driver-core/com/mongodb/client/model/Sorts.html>`.
339+ See the server manual documentation for more information on the :manual:`$text </reference/operator/query/text/>`
340+ query operator and the
341+ :manual:`$meta </reference/operator/aggregation/meta/>`
342+ aggregation pipeline operator.
0 commit comments