It is really absurd how mongoengine has such arcane documentation. I am trying to do a simple (update if exists query) based on a few columns/fields. What I mean by that is
if fieldA has valueA and
fieldB has valueB and
fieldC has valueC
then
update fieldD with newValueD,
fieldE with newValueE
I could do it in the method mentioned below but I am pretty sure there is a really simple upsert syntax where if I mention the fields and values then it matches it across the collection, updates if they match and inserts if they don't
def __generateRemoteData(data):
"""
Utils function to add remote data to Mongo
"""
for datum in data:
query = RemoteGraph.objects(
Q(fieldA=datum.get('fieldA')) and
Q(fieldB=datum.get('fieldB')) and
Q(fieldC=datum.get('fieldC')) and
Q(fieldD=datum.get('fieldD')) and
Q(fieldE=datum.get('fieldE')) and
Q(date=datum.get('date'))
)
if not query:
RemoteGraph(
fieldA=datum.get('fieldA'),
fieldB=datum.get('fieldB'),
fieldC=datum.get('fieldC'),
fieldD=datum.get('fieldD'),
fieldE=datum.get('fieldE'),
date=datum.get('date'),
fieldF=datum.get('fieldF'),
fieldG=datum.get('fieldG'),
).save()
else:
query.update(
set__fieldF=datum.get('fieldF'),
set__fieldG=datum.get('fieldG'),
)
Looking for a more pythonic way to do this.
I have looked into upsert
, insert
, modify
, save
, update
, update_one
First of all Q() combines only with bitwise operators. And the meaning of Q is in combining &
and |
operators. Detailed here
There is a special option upsert=True
of the QuerySet::update
method. Upsert – force an insertion of a new document if RemoteGraph.objects(a=val_a, b=val_b, c=val_c, date=date)
founds no one document.
RemoteGraph.objects(
a=val_a, b=val_b, c=val_c, date=date
).update(
a=val_a, b=val_b, c=val_c, date=date
)
Also there are [QuerySet::modify][3]
and QuerySet::update_one
method, they could upsert new document too, but unlike of QuerySet::update
, they will update only first document from QuerySet
.
And finally there is a QuerySet::upsert_one
. The name says it all. One noticeable distinction it raises an Exception if the QuerySet contains more than one document. Actually QuerySet::update_one
and QuerySet::upsert_one
are small wrappers over QuerySet::update