Skip to content

Commit 4b16e2c

Browse files
jason-price-mongodbjeff-allen-mongo
jason-price-mongodb
authored andcommitted
DOCS-13309 short circuit evaluation
1 parent b74862d commit 4b16e2c

File tree

5 files changed

+107
-28
lines changed

5 files changed

+107
-28
lines changed

source/includes/and-or-behavior.rst

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
To allow the query engine to optimize queries, |and-or| handles
2+
errors as follows:
3+
4+
- If any expression supplied to |and-or| would cause an error when
5+
evaluated alone, the |and-or| containing the expression may cause an
6+
error but an error is not guaranteed.
7+
8+
- An expression supplied after the first expression supplied to |and-or|
9+
may cause an error even if the first expression evaluates to
10+
|true-false|.
11+
12+
For example, the following query *always* produces an error if ``$x`` is
13+
``0``:
14+
15+
.. code-block:: javascript
16+
17+
db.example.find( {
18+
$expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] }
19+
} )
20+
21+
The following query, which contains multiple expressions supplied to
22+
|and-or|, *may* produce an error if there is any document where ``$x``
23+
is ``0``:

source/reference/operator/aggregation/and.txt

+22-8
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ Definition
1616
.. expression:: $and
1717

1818
Evaluates one or more expressions and returns ``true`` if *all* of
19-
the expressions are ``true`` or if evoked with no argument
19+
the expressions are ``true`` or if run with no argument
2020
expressions. Otherwise, :expression:`$and` returns ``false``.
2121

22-
:expression:`$and` has the following syntax:
22+
:expression:`$and` syntax:
2323

2424
.. code-block:: javascript
2525

@@ -33,9 +33,6 @@ Definition
3333
Behavior
3434
--------
3535

36-
:expression:`$and` uses short-circuit logic: the operation stops
37-
evaluation after encountering the first ``false`` expression.
38-
3936
.. include:: /includes/extracts/fact-agg-boolean-and.rst
4037

4138
.. list-table::
@@ -66,10 +63,27 @@ evaluation after encountering the first ``false`` expression.
6663

6764
- ``false``
6865

66+
Error Handling
67+
--------------
68+
69+
.. |and-or| replace:: ``$and``
70+
.. |true-false| replace:: ``false``
71+
72+
.. include:: /includes/and-or-behavior.rst
73+
74+
.. code-block:: javascript
75+
76+
db.example.find( {
77+
$and: [
78+
{ x: { $ne: 0 } },
79+
{ $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } }
80+
]
81+
} )
82+
6983
Example
7084
-------
7185

72-
Create an example ``inventory`` collection with the following documents:
86+
Create an example ``inventory`` collection with these documents:
7387

7488
.. code-block:: javascript
7589

@@ -81,7 +95,7 @@ Create an example ``inventory`` collection with the following documents:
8195
{ "_id" : 5, "item" : "VWZ2", description: "product 5", qty: 180 }
8296
])
8397

84-
The following operation uses the :expression:`$and` operator to
98+
This operation uses the :expression:`$and` operator to
8599
determine if ``qty`` is greater than 100 *and* less than ``250``:
86100

87101
.. code-block:: javascript
@@ -99,7 +113,7 @@ determine if ``qty`` is greater than 100 *and* less than ``250``:
99113
]
100114
)
101115

102-
The operation returns the following results:
116+
The operation returns these results:
103117

104118
.. code-block:: javascript
105119

source/reference/operator/aggregation/or.txt

+17-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ Definition
3131
Behavior
3232
--------
3333

34-
:expression:`$or` uses short-circuit logic: the operation stops
35-
evaluation after encountering the first ``true`` expression.
36-
3734
.. include:: /includes/extracts/fact-agg-boolean-or.rst
3835

3936
.. list-table::
@@ -60,6 +57,23 @@ evaluation after encountering the first ``true`` expression.
6057

6158
- ``false``
6259

60+
Error Handling
61+
--------------
62+
63+
.. |and-or| replace:: ``$or``
64+
.. |true-false| replace:: ``true``
65+
66+
.. include:: /includes/and-or-behavior.rst
67+
68+
.. code-block:: javascript
69+
70+
db.example.find( {
71+
$or: [
72+
{ x: { $eq: 0 } },
73+
{ $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } }
74+
]
75+
} )
76+
6377
Example
6478
-------
6579

source/reference/operator/query/and.txt

+28-17
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,51 @@ $and
1414

1515
*Syntax*: ``{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }``
1616

17-
:query:`$and` performs a logical ``AND`` operation on an array
18-
of *one or more* expressions (e.g. ``<expression1>``,
19-
``<expression2>``, etc.) and selects the documents that satisfy
20-
*all* the expressions in the array. The :query:`$and` operator
21-
uses *short-circuit evaluation*. If the first expression
22-
(e.g. ``<expression1>``) evaluates to ``false``, MongoDB will not
23-
evaluate the remaining expressions.
17+
:query:`$and` performs a logical ``AND`` operation on an array of
18+
*one or more* expressions (``<expression1>``, ``<expression2>``, and
19+
so on) and selects the documents that satisfy *all* the expressions.
2420

2521
.. note::
2622

2723
MongoDB provides an implicit ``AND`` operation when specifying a
2824
comma separated list of expressions.
2925

26+
Behavior
27+
--------
28+
29+
.. |and-or| replace:: ``$and``
30+
.. |true-false| replace:: ``false``
31+
32+
.. include:: /includes/and-or-behavior.rst
33+
34+
.. code-block:: javascript
35+
36+
db.example.find( {
37+
$and: [
38+
{ x: { $ne: 0 } },
39+
{ $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } }
40+
]
41+
} )
42+
3043
Examples
3144
--------
3245

3346
``AND`` Queries With Multiple Expressions Specifying the Same Field
3447
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3548

36-
Consider the following example:
49+
Consider this query:
3750

3851
.. code-block:: javascript
3952

4053
db.inventory.find( { $and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } ] } )
4154

42-
This query will select all documents in the ``inventory``
43-
collection where:
55+
The query selects all documents in the ``inventory`` collection where:
4456

4557
- the ``price`` field value is not equal to ``1.99`` **and**
4658
- the ``price`` field exists.
4759

48-
This query can be also be constructed with an implicit ``AND``
49-
operation by combining the operator expressions for the ``price``
50-
field. For example, this query can be written as:
60+
The query can be rewritten with an implicit ``AND`` operation that
61+
combines the operator expressions for the ``price`` field:
5162

5263
.. code-block:: javascript
5364

@@ -56,7 +67,7 @@ field. For example, this query can be written as:
5667
``AND`` Queries With Multiple Expressions Specifying the Same Operator
5768
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5869

59-
Consider the following example:
70+
Consider this query:
6071

6172
.. code-block:: javascript
6273

@@ -67,14 +78,14 @@ Consider the following example:
6778
]
6879
} )
6980

70-
This query will select all documents where:
81+
The query selects all documents where:
7182

7283
- the ``qty`` field value is less than ``10`` or greater than ``50``, **and**
7384
- the ``sale`` field value is equal to ``true`` **or** the ``price``
7485
field value is less than ``5``.
7586

76-
This query cannot be constructed using an implicit ``AND`` operation,
77-
because it uses the :query:`$or` operator more than once.
87+
The query cannot use an implicit ``AND`` operation because it uses the
88+
:query:`$or` operator more than once.
7889

7990
.. seealso::
8091

source/reference/operator/query/or.txt

+17
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,20 @@ You may nest :query:`$or` operations.
118118
- :method:`~db.collection.find()`
119119
- :method:`~cursor.sort()`
120120
- :query:`$in`
121+
122+
Error Handling
123+
~~~~~~~~~~~~~~
124+
125+
.. |and-or| replace:: ``$or``
126+
.. |true-false| replace:: ``true``
127+
128+
.. include:: /includes/and-or-behavior.rst
129+
130+
.. code-block:: javascript
131+
132+
db.example.find( {
133+
$or: [
134+
{ x: { $eq: 0 } },
135+
{ $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } }
136+
]
137+
} )

0 commit comments

Comments
 (0)