From 0b9a6c123af3373cef1c5b474fb6abe41b165127 Mon Sep 17 00:00:00 2001 From: kay Date: Fri, 8 Feb 2013 00:32:37 -0500 Subject: [PATCH 1/5] positional and elemMatch projection operators --- source/reference/operator/positional.txt | 50 +++--- source/reference/projection/elemMatch.txt | 170 +++++++++++++++++---- source/reference/projection/positional.txt | 130 ++++++++++++++++ 3 files changed, 301 insertions(+), 49 deletions(-) create mode 100644 source/reference/projection/positional.txt diff --git a/source/reference/operator/positional.txt b/source/reference/operator/positional.txt index f9028790ac3..880c54103d8 100644 --- a/source/reference/operator/positional.txt +++ b/source/reference/operator/positional.txt @@ -4,24 +4,36 @@ .. default-domain:: mongodb +This page documents the use of the ``positional $`` operator to +identify the array element to update in the :method:`update() +` method. For the positional ``$`` projection +operator used to return an array element from a read operation, see the +:doc:`positional $ ` projection +operator. + .. operator:: $ *Syntax*: ``{ ".$" : value }`` The positional :operator:`$` operator identifies an element in an ``array`` field to update without explicitly specifying the position - of the element in the array. The positional :operator:`$` operator, - when used with the :method:`update() - ` method and acts as a placeholder for the - **first match** of the update ``query selector``: + of the element in the array. - .. code-block:: javascript + When used with the :method:`update() ` + method, + + - the positional :operator:`$` operator acts as a placeholder for + the **first** element that matches the :ref:`query document + `, and - db.collection.update( { }, { : { "array.$" : value } } ) + - the ``array`` field **must** appear as part of the ``query + document``. + + .. code-block:: javascript - The ``array`` field **must** appear as part of the ``query selector``. + db.collection.update( { : value ... }, { : { ".$" : value } } ) - Consider the following collection ``students`` with the following documents: + Consider a collection ``students`` with the following documents: .. code-block:: javascript @@ -38,7 +50,8 @@ db.students.update( { _id: 1, grades: 80 }, { $set: { "grades.$" : 82 } } ) Remember that the positional :operator:`$` operator acts as a - placeholder for the **first match** of the update ``query selector``. + placeholder for the **first match** of the update :ref:`query + document `. The positional :operator:`$` operator facilitates updates to arrays that contain embedded documents. Use the positional :operator:`$` @@ -66,18 +79,17 @@ db.students.update( { _id: 4, "grades.grade": 85 }, { $set: { "grades.$.std" : 6 } } ) - Consider the following behaviors when using the positional - :operator:`$` operator: - - - Do not use the positional operator :operator:`$` with - :term:`upsert` operations because, inserts will use the ``$`` as a field name - in the inserted document. + .. note:: + + - Do not use the positional operator :operator:`$` with + :term:`upsert` operations because inserts will use the ``$`` as + a field name in the inserted document. - - When used with the :operator:`$unset` operator, the positional - :operator:`$` operator does not remove the matching element from - the array but rather sets it to ``null``. + - When used with the :operator:`$unset` operator, the positional + :operator:`$` operator does not remove the matching element + from the array but rather sets it to ``null``. .. seealso:: - + :method:`update() `, :operator:`$set` and :operator:`$unset` diff --git a/source/reference/projection/elemMatch.txt b/source/reference/projection/elemMatch.txt index ad367ba0ed4..3dbfb04d16e 100644 --- a/source/reference/projection/elemMatch.txt +++ b/source/reference/projection/elemMatch.txt @@ -10,49 +10,159 @@ $elemMatch (projection) .. versionadded:: 2.2 - Use the :projection:`$elemMatch` projection operator to limit the - response of a query to a single matching element of an - array. Consider the following: + The :projection:`$elemMatch` projection operator limits the contents + of an array field that is included in the query results to contain + only the element that matches the query condition. + + *Syntax*: ``{ $elemMatch: { : } }`` + + The ```` can be documents that contains :ref:`query operator + expressions `. + + .. note:: + + - If multiple elements match the :projection:`$elemMatch` + condition, the operator returns the **first** matching element + in the ```` field. + + - The :projection:`$elemMatch` project operator is similar to the + :doc:`positional $ ` + projection operator. + + The examples on the :projection:`$elemMatch` project operator + assumes a collection ``school`` with the following documents: + + .. code-block:: javascript + + { + _id: 1, + zipcode: 63109, + students: [ + { name: "john", school: 102, age: 10 }, + { name: "jess", school: 102, age: 11 }, + { name: "jeff", school: 108, age: 15 } + ] + } + { + _id: 2, + zipcode: 63110, + students: [ + { name: "ajax", school: 100, age: 7 }, + { name: "achilles", school: 100, age: 8 }, + ] + } + + { + _id: 3, + zipcode: 63109, + students: [ + { name: "ajax", school: 100, age: 7 }, + { name: "achilles", school: 100, age: 8 }, + ] + } + + { + _id: 4, + zipcode: 63109, + students: [ + { name: "barney", school: 102, age: 7 }, + ] + } .. example:: - Given the following document fragment: + The following :method:`find() ` operation + queries for all documents where the value of the ``zipcode`` + field is ``63109``. The projection excludes the ``_id`` field and + only includes the **first** matching element of the + ``students`` array where the ``school`` field has a value of + ``102``: .. code-block:: javascript - { - _id: ObjectId(), - zipcode: 63109, - dependents: [ - { name: "john", school: 102, age: 10 }, - { name: "jess", school: 102, age: 11 }, - { name: "jeff", school: 108, age: 15 } - ] - } + db.schools.find( { zipcode: 63109 }, + { _id: 0, students: { $elemMatch: { school: 102 } } } ) - Consider the following :method:`find() ` - operation: + The operation returns the following documents: .. code-block:: javascript - var projection = { _id: 0, dependents: { $elemMatch: { school: 102 }}}; - db.students.find( { zipcode: 63109 }, projection); + { "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } + { } + { "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] } - The query would return all documents where the value of the - ``zipcode`` field is ``63109``, while the projection excludes - the ``_id`` field and only includes the first matching element of - the ``dependents`` array where the ``school`` element has a value of - ``102``. The documents would take the following form: + - For the collection document with ``_id`` equal to ``1``, the + ``students`` array contains multiple elements with the + ``school`` field equal to ``102``. However, the + :projection:`$elemMatch` projection returns only the first + matching element from the array. + + - The empty document ``{ }`` corresponds to the document with the + ``_id`` equal to ``3`` where the value of the ``zipcode`` field + is ``63109``, **but** the ``students`` array does not contain + an element with a ``school`` field equal to ``102``. + + The :projection:`$elemMatch` projection can specify criteria on multiple + fields: + + .. example:: + + The following :method:`find() ` operation + queries for all documents where the value of the ``zipcode`` + field is ``63109``. The projection includes the **first** + matching element of the ``students`` array where the ``school`` + field has a value of ``102`` **and** the ``age`` field is greater + than ``10``: + + .. code-block:: javascript + + db.schools.find( { zipcode: 63109 }, + { students: { $elemMatch: { school: 102, age: { $gt: 10} } } } ) + + The operation returns the three documents that have ``zipcode`` equal to ``63109``: + + .. code-block:: javascript + + { "_id" : 1, "students" : [ { "name" : "jess", "school" : 102, "age" : 11 } ] } + { "_id" : 3 } + { "_id" : 4 } + + Documents with ``_id`` equal to ``3`` and ``_id`` equal to ``4`` + do not contain the ``students`` field since no element matched + the :projection:`$elemMatch` criteria. + + When the :method:`~db.collection.find()` method includes a + :method:`~cursor.sort()`, the :method:`~db.collection.find()` method + applies the :method:`~cursor.sort()` to order the matching documents + **before** it applies the projection. + + If an array field contains multiple documents with the same field + name and the :method:`~db.collection.find()` method includes a + :method:`~cursor.sort()` on that repeating field, the returned + documents may not reflect the sort order because the + :method:`~cursor.sort()` was applied to the elements of the array + before the :projection:`elemMatch` projection. + + .. example:: + + The following query includes a :method:`~cursor.sort()` to order + by descending ``students.age`` field: + + .. code-block:: javascript + + db.schools.find( { zipcode: 63109 }, { students: { $elemMatch: { school: 102 } } } ).sort( { "students.age": -1 } ) + + The operation applies the :method:`~cursor.sort()` to order the + documents that have the field ``zipcode`` equal to ``63109`` and + then applies the projection. The operation returns the three + documents in the following order: .. code-block:: javascript - { - dependents: [ - { name: "john", school: 102, age: 10 } - ] - } + { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } + { "_id" : 3 } + { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] } -.. note:: +.. seealso:: - The :projection:`$elemMatch` projection will only match one array - element per source document. + :doc:`positional $ ` projection operator \ No newline at end of file diff --git a/source/reference/projection/positional.txt b/source/reference/projection/positional.txt new file mode 100644 index 00000000000..53c93f6524a --- /dev/null +++ b/source/reference/projection/positional.txt @@ -0,0 +1,130 @@ +=============== +\$ (projection) +=============== + +.. default-domain:: mongodb + +.. note:: + This page documents the use of the ``positional $`` operator in the + :term:`projection` document of the :method:`~db.collection.find()` + and the :method:`~db.collection.findOne()` methods. For the use of + the positional ``$`` operator with the + :method:`~db.collection.update()` method, see the :doc:`positional $ + operator for updates ` . + +.. operator:: $ + + *Syntax*: ``{ ".$" : 1 }`` + + The positional :projection:`$` operator limits the contents of the + ```` field that is included in the query results to contain + only a **single** matching element. + + Used with the :method:`~db.collection.find()` or + :method:`~db.collection.findOne()` method in the :term:`projection` + document: + + - The :projection:`$` projection operator limits the content of the + ```` field to the **first** element that matches the + :ref:`query document `, and + + - The ```` field **must** appear in the ``query document``. + + .. code-block:: javascript + + db.collection.find( { : value ... }, + { ".$": 1 } ) + db.collection.find( { : value ...}, + { ".$": 1 } ) + + Consider a collection ``students`` with the following documents: + + .. code-block:: javascript + + { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] } + { "_id" : 2, "semester" : 1, "grades" : [ 90, 88, 92 ] } + { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] } + { "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] } + { "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] } + { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] } + + The following example queries for documents where the ``semester`` + field equals ``1`` and the ``grades`` array contains an element + greater than or equal to ``85``. The example includes the + :projection:`$` projection operator to return only the element in + the ``grades`` array that matches the query criteria; the ``_id`` + field is by default implicitly included in the results: + + .. code-block:: javascript + + db.students.find( { semester: 1, grades: { $gte: 85 } }, { "grades.$": 1 } ) + + The read operation returns the following matching documents: + + .. code-block:: javascript + + { "_id" : 1, "grades" : [ 87 ] } + { "_id" : 2, "grades" : [ 90 ] } + { "_id" : 3, "grades" : [ 85 ] } + + Although the array field ``grades`` may contain multiple elements + that are greater than or equal to ``85``, the :projection:`$` + projection operator returns only the first matching element from the + array. + + .. important:: + When the :method:`~db.collection.find()` method includes a + :method:`~cursor.sort()`, the :method:`~db.collection.find()` + method applies the :method:`~cursor.sort()` to order the matching + documents **before** it applies the positional :projection:`$` + projection operator. + + If an array field contains multiple documents with the same field + name and the :method:`~db.collection.find()` method includes a + :method:`~cursor.sort()` on that repeating field, the returned + documents may not reflect the sort order because the sort was + applied to the elements of the array before the :projection:`$` + projection operator. + + Consider the following documents in the ``students`` collection + where the ``grades`` field is an array of documents; each document + contain the three field names ``grade``, ``mean``, and ``std``: + + .. code-block:: javascript + + { "_id" : 7, semester: 3, "grades" : [ { grade: 80, mean: 75, std: 8 }, + { grade: 85, mean: 90, std: 5 }, + { grade: 90, mean: 85, std: 3 } ] } + + { "_id" : 8, semester: 3, "grades" : [ { grade: 92, mean: 88, std: 8 }, + { grade: 78, mean: 90, std: 5 }, + { grade: 88, mean: 85, std: 3 } ] } + + The following example queries for documents with the array field + ``grades`` that contain an element with the ``mean`` greater than + ``70``. The query includes a projection to return the ``_id`` field + and only the matching array element in the ``grades`` array. The + query also includes a :method:`~cursor.sort()` to order by ascending + ``grades.grade`` field: + + .. code-block:: javascript + + db.students.find( { "grades.mean": { $gt: 70 } }, { "grades.$": 1 } ).sort( { "grades.grade": 1 } ) + + The :method:`~db.collection.find()` method applies the + :method:`~cursor.sort()` to the matching documents **before** it + applies the :projection:`$` projection operator on the ``grades`` + array. Thus, the results with the projected array elements do not + reflect the ascending ``grades.grade`` sort order: + + .. code-block:: javascript + + { "_id" : 8, "grades" : [ { "grade" : 92, "mean" : 88, "std" : 8 } ] } + { "_id" : 7, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 } ] } + +.. JEFF/BEN -- wanted to double check, currently we can't do a projection of { "grades.$.grade": 1 } to + return just the grade field, yes? When I tried the command, it acted as though it were a projection of + just { "grades.$": 1 } + +.. seealso:: + :doc:`/reference/projection/elemMatch` \ No newline at end of file From 7c02dd6556d5264cb27670574918bfa7400a8f36 Mon Sep 17 00:00:00 2001 From: kay Date: Fri, 8 Feb 2013 12:06:06 -0500 Subject: [PATCH 2/5] incorporate ben's comments for elemMatch and positional projection operators --- source/reference/projection/elemMatch.txt | 14 +++---- source/reference/projection/positional.txt | 44 ++++++++++++++++++---- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/source/reference/projection/elemMatch.txt b/source/reference/projection/elemMatch.txt index 3dbfb04d16e..07f54e4db07 100644 --- a/source/reference/projection/elemMatch.txt +++ b/source/reference/projection/elemMatch.txt @@ -25,11 +25,11 @@ $elemMatch (projection) condition, the operator returns the **first** matching element in the ```` field. - - The :projection:`$elemMatch` project operator is similar to the + - The :projection:`$elemMatch` projection operator is similar to the :doc:`positional $ ` projection operator. - The examples on the :projection:`$elemMatch` project operator + The examples on the :projection:`$elemMatch` projection operator assumes a collection ``school`` with the following documents: .. code-block:: javascript @@ -91,11 +91,11 @@ $elemMatch (projection) { } { "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] } - - For the collection document with ``_id`` equal to ``1``, the - ``students`` array contains multiple elements with the - ``school`` field equal to ``102``. However, the - :projection:`$elemMatch` projection returns only the first - matching element from the array. + - For the document with ``_id`` equal to ``1``, the ``students`` + array contains multiple elements with the ``school`` field + equal to ``102``. However, the :projection:`$elemMatch` + projection returns only the first matching element from the + array. - The empty document ``{ }`` corresponds to the document with the ``_id`` equal to ``3`` where the value of the ``zipcode`` field diff --git a/source/reference/projection/positional.txt b/source/reference/projection/positional.txt index 53c93f6524a..c7c65c15990 100644 --- a/source/reference/projection/positional.txt +++ b/source/reference/projection/positional.txt @@ -18,7 +18,7 @@ The positional :projection:`$` operator limits the contents of the ```` field that is included in the query results to contain - only a **single** matching element. + the **first** matching element. Used with the :method:`~db.collection.find()` or :method:`~db.collection.findOne()` method in the :term:`projection` @@ -26,16 +26,32 @@ - The :projection:`$` projection operator limits the content of the ```` field to the **first** element that matches the - :ref:`query document `, and + :ref:`query document `. - - The ```` field **must** appear in the ``query document``. + - The ```` field **must** appear in the :ref:`query document + ` - .. code-block:: javascript + .. code-block:: javascript + + db.collection.find( { : value ... }, + { ".$": 1 } ) + db.collection.find( { : value ...}, + { ".$": 1 } ) + + The ```` can be documents that contains :ref:`query operator + expressions `. + + - Only **one** positional :projection:`$` operator can appear in the + projection document. + + - Only **one** array field can appear in the :ref:`query document + `; i.e. the following query is + **incorrect**: - db.collection.find( { : value ... }, - { ".$": 1 } ) - db.collection.find( { : value ...}, - { ".$": 1 } ) + .. code-block:: javascript + + db.collection.find( { : value, someOtherArray: value }, + { ".$": 1 } ) Consider a collection ``students`` with the following documents: @@ -122,6 +138,18 @@ { "_id" : 8, "grades" : [ { "grade" : 92, "mean" : 88, "std" : 8 } ] } { "_id" : 7, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 } ] } + .. note:: + + Since only **one** array field can appear in the ``query + document``, if the array contains documents, to specify criteria + on multiple fields of these documents, use the + :doc:`/reference/operator/elemMatch/` operator, e.g.: + + .. code-block:: javascript + + db.students.find( { grades: { $elemMatch: { mean: { $gt: 70 }, grade: { $gt:90 } } } }, + { "grades.$": 1 } ) + .. JEFF/BEN -- wanted to double check, currently we can't do a projection of { "grades.$.grade": 1 } to return just the grade field, yes? When I tried the command, it acted as though it were a projection of just { "grades.$": 1 } From cb672ac6960721c8e78dbf504f80af3a6a2420ab Mon Sep 17 00:00:00 2001 From: kay Date: Fri, 8 Feb 2013 17:09:04 -0500 Subject: [PATCH 3/5] incorporate Jeff's comments --- source/reference/projection/elemMatch.txt | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/source/reference/projection/elemMatch.txt b/source/reference/projection/elemMatch.txt index 07f54e4db07..16473ae7de2 100644 --- a/source/reference/projection/elemMatch.txt +++ b/source/reference/projection/elemMatch.txt @@ -73,23 +73,22 @@ $elemMatch (projection) The following :method:`find() ` operation queries for all documents where the value of the ``zipcode`` - field is ``63109``. The projection excludes the ``_id`` field and - only includes the **first** matching element of the - ``students`` array where the ``school`` field has a value of - ``102``: + field is ``63109``. The :projection:`$elemMatch` projection + returns only the **first** matching element of the ``students`` + array where the ``school`` field has a value of ``102``: .. code-block:: javascript db.schools.find( { zipcode: 63109 }, - { _id: 0, students: { $elemMatch: { school: 102 } } } ) + { students: { $elemMatch: { school: 102 } } } ) The operation returns the following documents: .. code-block:: javascript - { "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } - { } - { "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] } + { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } + { "_id" : 3 } + { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] } - For the document with ``_id`` equal to ``1``, the ``students`` array contains multiple elements with the ``school`` field @@ -97,10 +96,10 @@ $elemMatch (projection) projection returns only the first matching element from the array. - - The empty document ``{ }`` corresponds to the document with the - ``_id`` equal to ``3`` where the value of the ``zipcode`` field - is ``63109``, **but** the ``students`` array does not contain - an element with a ``school`` field equal to ``102``. + - The document with ``_id`` equal to ``3`` does not contain the + ``students`` field in the result since no element in its + ``students`` array matched the :projection:`$elemMatch` + criterion. The :projection:`$elemMatch` projection can specify criteria on multiple fields: From a978586889c47025b194706e36604406d0955797 Mon Sep 17 00:00:00 2001 From: kay Date: Wed, 13 Feb 2013 15:19:32 -0500 Subject: [PATCH 4/5] DOCS-368 projection operators position and elemmatch --- source/reference/projection/positional.txt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/reference/projection/positional.txt b/source/reference/projection/positional.txt index c7c65c15990..09b7a386c7e 100644 --- a/source/reference/projection/positional.txt +++ b/source/reference/projection/positional.txt @@ -33,9 +33,9 @@ .. code-block:: javascript - db.collection.find( { : value ... }, + db.collection.find( { : ... }, { ".$": 1 } ) - db.collection.find( { : value ...}, + db.collection.find( { : ...}, { ".$": 1 } ) The ```` can be documents that contains :ref:`query operator @@ -50,7 +50,7 @@ .. code-block:: javascript - db.collection.find( { : value, someOtherArray: value }, + db.collection.find( { : , : }, { ".$": 1 } ) Consider a collection ``students`` with the following documents: @@ -150,9 +150,5 @@ db.students.find( { grades: { $elemMatch: { mean: { $gt: 70 }, grade: { $gt:90 } } } }, { "grades.$": 1 } ) -.. JEFF/BEN -- wanted to double check, currently we can't do a projection of { "grades.$.grade": 1 } to - return just the grade field, yes? When I tried the command, it acted as though it were a projection of - just { "grades.$": 1 } - .. seealso:: :doc:`/reference/projection/elemMatch` \ No newline at end of file From 23240f387c56e8380502647143d22e1e84762fde Mon Sep 17 00:00:00 2001 From: kay Date: Thu, 14 Feb 2013 13:06:18 -0500 Subject: [PATCH 5/5] DOCS-368 projection operators - incorporate git comments --- source/reference/operator/positional.txt | 11 +- source/reference/projection/elemMatch.txt | 28 ++--- source/reference/projection/positional.txt | 140 ++++++++++----------- 3 files changed, 86 insertions(+), 93 deletions(-) diff --git a/source/reference/operator/positional.txt b/source/reference/operator/positional.txt index 880c54103d8..08815de5b87 100644 --- a/source/reference/operator/positional.txt +++ b/source/reference/operator/positional.txt @@ -4,20 +4,15 @@ .. default-domain:: mongodb -This page documents the use of the ``positional $`` operator to -identify the array element to update in the :method:`update() -` method. For the positional ``$`` projection -operator used to return an array element from a read operation, see the -:doc:`positional $ ` projection -operator. - .. operator:: $ *Syntax*: ``{ ".$" : value }`` The positional :operator:`$` operator identifies an element in an ``array`` field to update without explicitly specifying the position - of the element in the array. + of the element in the array. To project, or return, an array element + from a read operation, see the :doc:`$ + ` projection operator. When used with the :method:`update() ` method, diff --git a/source/reference/projection/elemMatch.txt b/source/reference/projection/elemMatch.txt index 16473ae7de2..4d668100fbb 100644 --- a/source/reference/projection/elemMatch.txt +++ b/source/reference/projection/elemMatch.txt @@ -12,22 +12,19 @@ $elemMatch (projection) The :projection:`$elemMatch` projection operator limits the contents of an array field that is included in the query results to contain - only the element that matches the query condition. - - *Syntax*: ``{ $elemMatch: { : } }`` - - The ```` can be documents that contains :ref:`query operator - expressions `. + only the array element that matches the :projection:`$elemMatch` + condition. .. note:: + - The elements of the array are documents. + - If multiple elements match the :projection:`$elemMatch` condition, the operator returns the **first** matching element - in the ```` field. - - - The :projection:`$elemMatch` projection operator is similar to the - :doc:`positional $ ` - projection operator. + in the array. + + - The :projection:`$elemMatch` projection operator is similar to + the positional :projection:`$` projection operator. The examples on the :projection:`$elemMatch` projection operator assumes a collection ``school`` with the following documents: @@ -99,7 +96,7 @@ $elemMatch (projection) - The document with ``_id`` equal to ``3`` does not contain the ``students`` field in the result since no element in its ``students`` array matched the :projection:`$elemMatch` - criterion. + condition. The :projection:`$elemMatch` projection can specify criteria on multiple fields: @@ -149,7 +146,10 @@ $elemMatch (projection) .. code-block:: javascript - db.schools.find( { zipcode: 63109 }, { students: { $elemMatch: { school: 102 } } } ).sort( { "students.age": -1 } ) + db.schools.find( + { zipcode: 63109 }, + { students: { $elemMatch: { school: 102 } } } + ).sort( { "students.age": -1 } ) The operation applies the :method:`~cursor.sort()` to order the documents that have the field ``zipcode`` equal to ``63109`` and @@ -164,4 +164,4 @@ $elemMatch (projection) .. seealso:: - :doc:`positional $ ` projection operator \ No newline at end of file + :projection:`$ (projection) <$>` operator diff --git a/source/reference/projection/positional.txt b/source/reference/projection/positional.txt index 09b7a386c7e..6474a59e989 100644 --- a/source/reference/projection/positional.txt +++ b/source/reference/projection/positional.txt @@ -4,25 +4,17 @@ .. default-domain:: mongodb -.. note:: - This page documents the use of the ``positional $`` operator in the - :term:`projection` document of the :method:`~db.collection.find()` - and the :method:`~db.collection.findOne()` methods. For the use of - the positional ``$`` operator with the - :method:`~db.collection.update()` method, see the :doc:`positional $ - operator for updates ` . - .. operator:: $ - *Syntax*: ``{ ".$" : 1 }`` - The positional :projection:`$` operator limits the contents of the ```` field that is included in the query results to contain - the **first** matching element. + the **first** matching element. To specify an array element to + update, see the :doc:`positional $ operator for updates + `. - Used with the :method:`~db.collection.find()` or - :method:`~db.collection.findOne()` method in the :term:`projection` - document: + Used in the :term:`projection` document of the + :method:`~db.collection.find()` method or the + :method:`~db.collection.findOne()` method: - The :projection:`$` projection operator limits the content of the ```` field to the **first** element that matches the @@ -53,40 +45,40 @@ db.collection.find( { : , : }, { ".$": 1 } ) - Consider a collection ``students`` with the following documents: + .. example:: - .. code-block:: javascript + A collection ``students`` contains the following documents: - { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] } - { "_id" : 2, "semester" : 1, "grades" : [ 90, 88, 92 ] } - { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] } - { "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] } - { "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] } - { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] } + .. code-block:: javascript - The following example queries for documents where the ``semester`` - field equals ``1`` and the ``grades`` array contains an element - greater than or equal to ``85``. The example includes the - :projection:`$` projection operator to return only the element in - the ``grades`` array that matches the query criteria; the ``_id`` - field is by default implicitly included in the results: + { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] } + { "_id" : 2, "semester" : 1, "grades" : [ 90, 88, 92 ] } + { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] } + { "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] } + { "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] } + { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] } - .. code-block:: javascript + In the following query, the projection ``{ "grades.$": 1 }`` + returns only the first element greater than or equal to ``85`` + for the ``grades`` field. - db.students.find( { semester: 1, grades: { $gte: 85 } }, { "grades.$": 1 } ) + .. code-block:: javascript - The read operation returns the following matching documents: + db.students.find( { semester: 1, grades: { $gte: 85 } }, + { "grades.$": 1 } ) - .. code-block:: javascript + The operation returns the following documents: - { "_id" : 1, "grades" : [ 87 ] } - { "_id" : 2, "grades" : [ 90 ] } - { "_id" : 3, "grades" : [ 85 ] } + .. code-block:: javascript - Although the array field ``grades`` may contain multiple elements - that are greater than or equal to ``85``, the :projection:`$` - projection operator returns only the first matching element from the - array. + { "_id" : 1, "grades" : [ 87 ] } + { "_id" : 2, "grades" : [ 90 ] } + { "_id" : 3, "grades" : [ 85 ] } + + Although the array field ``grades`` may contain multiple elements + that are greater than or equal to ``85``, the :projection:`$` + projection operator returns only the first matching element from the + array. .. important:: When the :method:`~db.collection.find()` method includes a @@ -102,53 +94,59 @@ applied to the elements of the array before the :projection:`$` projection operator. - Consider the following documents in the ``students`` collection - where the ``grades`` field is an array of documents; each document - contain the three field names ``grade``, ``mean``, and ``std``: + .. example:: - .. code-block:: javascript + A ``students`` collection contains the following documents + where the ``grades`` field is an array of documents; each document + contain the three field names ``grade``, ``mean``, and ``std``: - { "_id" : 7, semester: 3, "grades" : [ { grade: 80, mean: 75, std: 8 }, - { grade: 85, mean: 90, std: 5 }, - { grade: 90, mean: 85, std: 3 } ] } + .. code-block:: javascript - { "_id" : 8, semester: 3, "grades" : [ { grade: 92, mean: 88, std: 8 }, - { grade: 78, mean: 90, std: 5 }, - { grade: 88, mean: 85, std: 3 } ] } + { "_id" : 7, semester: 3, "grades" : [ { grade: 80, mean: 75, std: 8 }, + { grade: 85, mean: 90, std: 5 }, + { grade: 90, mean: 85, std: 3 } ] } - The following example queries for documents with the array field - ``grades`` that contain an element with the ``mean`` greater than - ``70``. The query includes a projection to return the ``_id`` field - and only the matching array element in the ``grades`` array. The - query also includes a :method:`~cursor.sort()` to order by ascending - ``grades.grade`` field: + { "_id" : 8, semester: 3, "grades" : [ { grade: 92, mean: 88, std: 8 }, + { grade: 78, mean: 90, std: 5 }, + { grade: 88, mean: 85, std: 3 } ] } - .. code-block:: javascript + In the following query, the projection ``{ "grades.$": 1 }`` + returns only the first element with the ``mean`` greater + than ``70`` for the ``grades`` field. The query also includes a + :method:`~cursor.sort()` to order by ascending ``grades.grade`` + field: - db.students.find( { "grades.mean": { $gt: 70 } }, { "grades.$": 1 } ).sort( { "grades.grade": 1 } ) + .. code-block:: javascript - The :method:`~db.collection.find()` method applies the - :method:`~cursor.sort()` to the matching documents **before** it - applies the :projection:`$` projection operator on the ``grades`` - array. Thus, the results with the projected array elements do not - reflect the ascending ``grades.grade`` sort order: + db.students.find( { "grades.mean": { $gt: 70 } }, + { "grades.$": 1 } + ).sort( { "grades.grade": 1 } ) - .. code-block:: javascript + The :method:`~db.collection.find()` method sorts the matching + documents **before** it applies the :projection:`$` projection + operator on the ``grades`` array. Thus, the results with the + projected array elements do not reflect the ascending + ``grades.grade`` sort order: + + .. code-block:: javascript - { "_id" : 8, "grades" : [ { "grade" : 92, "mean" : 88, "std" : 8 } ] } - { "_id" : 7, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 } ] } + { "_id" : 8, "grades" : [ { "grade" : 92, "mean" : 88, "std" : 8 } ] } + { "_id" : 7, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 } ] } - .. note:: + .. note:: - Since only **one** array field can appear in the ``query - document``, if the array contains documents, to specify criteria - on multiple fields of these documents, use the + Since only **one** array field can appear in the query document, + if the array contains documents, to specify criteria on multiple + fields of these documents, use the :doc:`/reference/operator/elemMatch/` operator, e.g.: .. code-block:: javascript - db.students.find( { grades: { $elemMatch: { mean: { $gt: 70 }, grade: { $gt:90 } } } }, + db.students.find( { grades: { $elemMatch: { + mean: { $gt: 70 }, + grade: { $gt:90 } + } } }, { "grades.$": 1 } ) .. seealso:: - :doc:`/reference/projection/elemMatch` \ No newline at end of file + :projection:`$elemMatch (projection) <$elemMatch>`