Skip to content

Commit 1386f49

Browse files
biniona-mongodbChris Cho
andauthored
DOCSP-9585 builders sort criteria (#59)
DOCSP-9585 builders sort criteria Co-authored-by: Chris Cho <[email protected]>
1 parent 2094ee5 commit 1386f49

File tree

1 file changed

+329
-0
lines changed

1 file changed

+329
-0
lines changed

source/fundamentals/builders/sort.txt

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)