Skip to content

improvements to findAndModify/db.collection.findAndModify ref #2078

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions source/reference/command/findAndModify.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Definition

The command has the following syntax:

.. code-block:: javascript
.. code-block:: none

{
findAndModify: <string>,
findAndModify: <collection-name>,
query: <document>,
sort: <document>,
remove: <boolean>,
Expand Down Expand Up @@ -92,13 +92,12 @@ The return document contains the following fields:
Behavior
--------

Upsert and Unique Index
~~~~~~~~~~~~~~~~~~~~~~~

When the :dbcommand:`findAndModify` command includes the ``upsert:
true`` option **and** the query field(s) is not uniquely indexed, the
command could insert a document multiple times in certain circumstances.
For instance, if multiple clients issue the :dbcommand:`findAndModify`
command and these commands complete the ``find`` phase before any one
starts the ``modify`` phase, these commands could insert the same
document.

Consider an example where no document with the name ``Andy`` exists and
multiple clients issue the following command:
Expand All @@ -117,19 +116,22 @@ multiple clients issue the following command:

If all the commands finish the ``query`` phase before any command
starts the ``modify`` phase, **and** there is no unique index on the
``name`` field, the commands may all result in an insert. To prevent
``name`` field, the commands may all perform an upsert, creating
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/all/each/

multiple duplicate documents.

To prevent
this condition, create a :ref:`unique index <index-type-unique>` on
the ``name`` field. With the unique index in place, then the multiple
:dbcommand:`findAndModify` commands would observe one of the
:dbcommand:`findAndModify` commands will exhibit one of the
following behaviors:

- Exactly one :dbcommand:`findAndModify` would successfully insert a
- Exactly one :dbcommand:`findAndModify` successfully inserts a
new document.

- Zero or more :dbcommand:`findAndModify` commands would update the
- Zero or more :dbcommand:`findAndModify` commands update the
newly inserted document.

- Zero or more :dbcommand:`findAndModify` commands would fail when
- Zero or more :dbcommand:`findAndModify` commands fail when
they attempted to insert a duplicate. If the command fails due to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/attempted/attempt/ - verb tense agreement with fail

a unique index constraint violation, you can retry the command.
Absent a delete of the document, the retry should not fail.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description: |
employs the same :ref:`query selectors <query-selectors>` as used in
the :method:`db.collection.find()` method. Although the query may
match multiple documents, |operation|
will select only one document to modify.
**will only select one document to modify**.
---
object:
name: db.collection.findAndModify()
Expand Down Expand Up @@ -100,7 +100,8 @@ description: |
When ``true``, |operation| creates a new
document if no document matches the ``query``, or if documents match
the ``query``, |operation| performs an
update.
update. To avoid multiple upserts, ensure the ``query`` fields
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/ensure the/ensure that the/

This is purely a matter of opinion, so you can ignore this if you think the original reads better.

are :ref:`uniquely indexed <index-type-unique>`.

The default is ``false``.
...
23 changes: 11 additions & 12 deletions source/reference/method/db.collection.findAndModify.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ modified document.
creates a new document. If ``new`` is ``false``, **and** a
``sort`` option, the method returns an empty document ``{}``.

Behaviors
---------
Behavior
--------

.. _upsert-and-unique-index:

Expand All @@ -76,10 +76,6 @@ Upsert and Unique Index
When :method:`~db.collection.findAndModify()` includes the ``upsert:
true`` option **and** the query field(s) is not uniquely indexed, the
method could insert a document multiple times in certain circumstances.
For instance, if multiple clients each invoke the method with the same
``query`` condition and these methods complete the ``find`` phase
before any of methods perform the ``modify`` phase, these methods could
result in the insertion of the same document.

In the following example, no document with the name ``Andy`` exists,
and multiple clients issue the following command:
Expand All @@ -96,19 +92,22 @@ and multiple clients issue the following command:
Then, if these clients' :method:`~db.collection.findAndModify()`
methods finish the ``query`` phase before any command starts the
``modify`` phase, **and** there is no unique index on the ``name``
field, the commands may all perform an upsert. To prevent this
field, the commands may all perform an upsert, creating
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/all/each/ as above.

multiple duplicate documents.

To prevent this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace "this condition" with the condition, given that its in its own paragraph now

condition, create a :ref:`unique index <index-type-unique>` on the
``name`` field. With the unique index in place, the multiple methods
would observe one of the following behaviors:
will exhibit one of the following behaviors:

- Exactly one :method:`~db.collection.findAndModify()` would
successfully insert a new document.
- Exactly one :method:`~db.collection.findAndModify()`
successfully inserts a new document.

- Zero or more :method:`~db.collection.findAndModify()` methods
would update the newly inserted document.
update the newly inserted document.

- Zero or more :method:`~db.collection.findAndModify()` methods
would fail when they attempted to insert a duplicate. If the
fail when they attempted to insert a duplicate. If the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/attempted/attempt/ as above.

method fails due to a unique index constraint violation, you can
retry the method. Absent a delete of the document, the retry
should not fail.
Expand Down