diff --git a/source/includes/and-or-behavior.rst b/source/includes/and-or-behavior.rst new file mode 100644 index 00000000000..e4bcb5bd226 --- /dev/null +++ b/source/includes/and-or-behavior.rst @@ -0,0 +1,23 @@ +To allow the query engine to optimize queries, |and-or| handles +errors as follows: + +- If any expression supplied to |and-or| would cause an error when + evaluated alone, the |and-or| containing the expression may cause an + error but an error is not guaranteed. + +- An expression supplied after the first expression supplied to |and-or| + may cause an error even if the first expression evaluates to + |true-false|. + +For example, the following query *always* produces an error if ``$x`` is +``0``: + +.. code-block:: javascript + + db.example.find( { + $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } + } ) + +The following query, which contains multiple expressions supplied to +|and-or|, *may* produce an error if there is any document where ``$x`` +is ``0``: diff --git a/source/reference/operator/aggregation/and.txt b/source/reference/operator/aggregation/and.txt index dce19d7d921..ae6f24d64dd 100644 --- a/source/reference/operator/aggregation/and.txt +++ b/source/reference/operator/aggregation/and.txt @@ -16,10 +16,10 @@ Definition .. expression:: $and Evaluates one or more expressions and returns ``true`` if *all* of - the expressions are ``true`` or if evoked with no argument + the expressions are ``true`` or if run with no argument expressions. Otherwise, :expression:`$and` returns ``false``. - :expression:`$and` has the following syntax: + :expression:`$and` syntax: .. code-block:: javascript @@ -33,9 +33,6 @@ Definition Behavior -------- -:expression:`$and` uses short-circuit logic: the operation stops -evaluation after encountering the first ``false`` expression. - .. include:: /includes/extracts/fact-agg-boolean-and.rst .. list-table:: @@ -66,10 +63,27 @@ evaluation after encountering the first ``false`` expression. - ``false`` +Error Handling +-------------- + +.. |and-or| replace:: ``$and`` +.. |true-false| replace:: ``false`` + +.. include:: /includes/and-or-behavior.rst + +.. code-block:: javascript + + db.example.find( { + $and: [ + { x: { $ne: 0 } }, + { $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } } + ] + } ) + Example ------- -Create an example ``inventory`` collection with the following documents: +Create an example ``inventory`` collection with these documents: .. code-block:: javascript @@ -81,7 +95,7 @@ Create an example ``inventory`` collection with the following documents: { "_id" : 5, "item" : "VWZ2", description: "product 5", qty: 180 } ]) -The following operation uses the :expression:`$and` operator to +This operation uses the :expression:`$and` operator to determine if ``qty`` is greater than 100 *and* less than ``250``: .. code-block:: javascript @@ -99,7 +113,7 @@ determine if ``qty`` is greater than 100 *and* less than ``250``: ] ) -The operation returns the following results: +The operation returns these results: .. code-block:: javascript diff --git a/source/reference/operator/aggregation/or.txt b/source/reference/operator/aggregation/or.txt index eb9a2e4ada8..4ef0c54e515 100644 --- a/source/reference/operator/aggregation/or.txt +++ b/source/reference/operator/aggregation/or.txt @@ -31,9 +31,6 @@ Definition Behavior -------- -:expression:`$or` uses short-circuit logic: the operation stops -evaluation after encountering the first ``true`` expression. - .. include:: /includes/extracts/fact-agg-boolean-or.rst .. list-table:: @@ -60,6 +57,23 @@ evaluation after encountering the first ``true`` expression. - ``false`` +Error Handling +-------------- + +.. |and-or| replace:: ``$or`` +.. |true-false| replace:: ``true`` + +.. include:: /includes/and-or-behavior.rst + +.. code-block:: javascript + + db.example.find( { + $or: [ + { x: { $eq: 0 } }, + { $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } } + ] + } ) + Example ------- diff --git a/source/reference/operator/query/and.txt b/source/reference/operator/query/and.txt index fd5e99dae4b..4c5ccdb1d3b 100644 --- a/source/reference/operator/query/and.txt +++ b/source/reference/operator/query/and.txt @@ -14,40 +14,51 @@ $and *Syntax*: ``{ $and: [ { }, { } , ... , { } ] }`` - :query:`$and` performs a logical ``AND`` operation on an array - of *one or more* expressions (e.g. ````, - ````, etc.) and selects the documents that satisfy - *all* the expressions in the array. The :query:`$and` operator - uses *short-circuit evaluation*. If the first expression - (e.g. ````) evaluates to ``false``, MongoDB will not - evaluate the remaining expressions. + :query:`$and` performs a logical ``AND`` operation on an array of + *one or more* expressions (````, ````, and + so on) and selects the documents that satisfy *all* the expressions. .. note:: MongoDB provides an implicit ``AND`` operation when specifying a comma separated list of expressions. +Behavior +-------- + +.. |and-or| replace:: ``$and`` +.. |true-false| replace:: ``false`` + +.. include:: /includes/and-or-behavior.rst + +.. code-block:: javascript + + db.example.find( { + $and: [ + { x: { $ne: 0 } }, + { $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } } + ] + } ) + Examples -------- ``AND`` Queries With Multiple Expressions Specifying the Same Field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Consider the following example: +Consider this query: .. code-block:: javascript db.inventory.find( { $and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } ] } ) -This query will select all documents in the ``inventory`` -collection where: +The query selects all documents in the ``inventory`` collection where: - the ``price`` field value is not equal to ``1.99`` **and** - the ``price`` field exists. -This query can be also be constructed with an implicit ``AND`` -operation by combining the operator expressions for the ``price`` -field. For example, this query can be written as: +The query can be rewritten with an implicit ``AND`` operation that +combines the operator expressions for the ``price`` field: .. code-block:: javascript @@ -56,7 +67,7 @@ field. For example, this query can be written as: ``AND`` Queries With Multiple Expressions Specifying the Same Operator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Consider the following example: +Consider this query: .. code-block:: javascript @@ -67,14 +78,14 @@ Consider the following example: ] } ) -This query will select all documents where: +The query selects all documents where: - the ``qty`` field value is less than ``10`` or greater than ``50``, **and** - the ``sale`` field value is equal to ``true`` **or** the ``price`` field value is less than ``5``. -This query cannot be constructed using an implicit ``AND`` operation, -because it uses the :query:`$or` operator more than once. +The query cannot use an implicit ``AND`` operation because it uses the +:query:`$or` operator more than once. .. seealso:: diff --git a/source/reference/operator/query/or.txt b/source/reference/operator/query/or.txt index 1e170d899eb..2fceaa6cc88 100644 --- a/source/reference/operator/query/or.txt +++ b/source/reference/operator/query/or.txt @@ -118,3 +118,20 @@ You may nest :query:`$or` operations. - :method:`~db.collection.find()` - :method:`~cursor.sort()` - :query:`$in` + +Error Handling +~~~~~~~~~~~~~~ + +.. |and-or| replace:: ``$or`` +.. |true-false| replace:: ``true`` + +.. include:: /includes/and-or-behavior.rst + +.. code-block:: javascript + + db.example.find( { + $or: [ + { x: { $eq: 0 } }, + { $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } } + ] + } )