Skip to content

Commit bf6f4c4

Browse files
author
Omer Katz
committed
Merge pull request MongoEngine#1167 from BeardedSteve/upsert_one
Upsert one
2 parents a6e996d + fc3db79 commit bf6f4c4

File tree

5 files changed

+40
-3
lines changed

5 files changed

+40
-3
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,4 @@ that much better:
231231
* Lars Butler (https://github.com/larsbutler)
232232
* George Macon (https://github.com/gmacon)
233233
* Ashley Whetter (https://github.com/AWhetter)
234+
* Steven Rossiter (https://github.com/BeardedSteve)

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Changelog
55
Changes in 0.10.4 - DEV
66
=======================
77
- SaveConditionError is now importable from the top level package. #1165
8+
- upsert_one method added. #1157
89

910
Changes in 0.10.3
1011
=================

mongoengine/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
__all__ = (list(document.__all__) + fields.__all__ + connection.__all__ +
1515
list(queryset.__all__) + signals.__all__ + list(errors.__all__))
1616

17-
VERSION = (0, 10, 1)
17+
VERSION = (0, 10, 4)
1818

1919

2020
def get_version():

mongoengine/queryset/base.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,32 @@ def update(self, upsert=False, multi=True, write_concern=None,
471471
raise OperationError(message)
472472
raise OperationError(u'Update failed (%s)' % unicode(err))
473473

474+
475+
def upsert_one(self, write_concern=None, **update):
476+
"""Overwrite or add the first document matched by the query.
477+
478+
:param write_concern: Extra keyword arguments are passed down which
479+
will be used as options for the resultant
480+
``getLastError`` command. For example,
481+
``save(..., write_concern={w: 2, fsync: True}, ...)`` will
482+
wait until at least two servers have recorded the write and
483+
will force an fsync on the primary server.
484+
:param update: Django-style update keyword arguments
485+
486+
:returns the new or overwritten document
487+
488+
.. versionadded:: 0.10.2
489+
"""
490+
491+
atomic_update = self.update(multi=False, upsert=True, write_concern=write_concern,
492+
full_result=True,**update)
493+
494+
if atomic_update['updatedExisting']:
495+
document = self.get()
496+
else:
497+
document = self._document.objects.with_id(atomic_update['upserted'])
498+
return document
499+
474500
def update_one(self, upsert=False, write_concern=None, **update):
475501
"""Perform an atomic update on the fields of the first document
476502
matched by the query.

tests/queryset/queryset.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,12 +680,21 @@ def test_upsert(self):
680680
def test_upsert_one(self):
681681
self.Person.drop_collection()
682682

683-
self.Person.objects(name="Bob", age=30).update_one(upsert=True)
683+
bob = self.Person.objects(name="Bob", age=30).upsert_one()
684684

685-
bob = self.Person.objects.first()
686685
self.assertEqual("Bob", bob.name)
687686
self.assertEqual(30, bob.age)
688687

688+
bob.name = "Bobby"
689+
bob.save()
690+
691+
bobby = self.Person.objects(name="Bobby", age=30).upsert_one()
692+
693+
self.assertEqual("Bobby", bobby.name)
694+
self.assertEqual(30, bobby.age)
695+
self.assertEqual(bob.id, bobby.id)
696+
697+
689698
def test_set_on_insert(self):
690699
self.Person.drop_collection()
691700

0 commit comments

Comments
 (0)