-
Notifications
You must be signed in to change notification settings - Fork 1.7k
DOCS-368 Elemmatch and positional projection operators #652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
0b9a6c1
positional and elemMatch projection operators
kay-kim 7c02dd6
incorporate ben's comments for elemMatch and positional projection op…
kay-kim cb672ac
incorporate Jeff's comments
kay-kim a978586
DOCS-368 projection operators position and elemmatch
kay-kim 23240f3
DOCS-368 projection operators - incorporate git comments
kay-kim File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,49 +10,158 @@ $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: { <array>: <value> } }`` | ||
|
||
The ``<value>`` can be documents that contains :ref:`query operator | ||
expressions <query-selectors-comparison>`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can make : more clear? |
||
|
||
.. note:: | ||
|
||
- If multiple elements match the :projection:`$elemMatch` | ||
condition, the operator returns the **first** matching element | ||
in the ``<array>`` field. | ||
|
||
- The :projection:`$elemMatch` projection operator is similar to the | ||
:doc:`positional $ </reference/projection/positional>` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I take it cross references for :operator: :/ |
||
projection operator. | ||
|
||
The examples on the :projection:`$elemMatch` projection 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() <db.collection.find()>` operation | ||
queries for all documents where the value of the ``zipcode`` | ||
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 | ||
|
||
{ | ||
_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 }, | ||
{ students: { $elemMatch: { school: 102 } } } ) | ||
|
||
Consider the following :method:`find() <db.collection.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); | ||
{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } | ||
{ "_id" : 3 } | ||
{ "_id" : 4, "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 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 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: | ||
|
||
.. example:: | ||
|
||
The following :method:`find() <db.collection.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 $ </reference/projection/positional>` projection operator |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we can just put this in the body of the object definition, so that it says :operator:
$
provides access introspect sub documents located within arrays in z context. see y to project)