TypeError: update() got multiple values for argument 'upsert'

853 views
Skip to first unread message

Andrew Pennebaker

unread,
Sep 15, 2015, 11:55:37 AM9/15/15
to mongodb-user
I'm writing some Python code to update a contest's last backfilled date. I can do this manually in the mongo shell, but when I try to translate the query into pymongo syntax, something goes wrong.

Code:

        ShoutletContestConfig.objects().update(
            { '_id': contest },
            { '$set': { 'config.submission.twitter_retweet_last_backfilled': backfill_date } },
            **{ 'upsert': False }
        )

(`ShoutletContestConfig` is a mongo Document subclass.)

Error:

    TypeError: update() got multiple values for argument 'upsert'

Attempted mitigation:

* Omit the upsert parameter (Hey, the mongo shell is smart enough to pick a default). When I do this in pymongo, it complains that the query is missing the upsert parameter.
* Literally type `upsert=False` instead of the dict splat, just in case. Nope, same error.
* The pymongo API docs are ambiguous on the proper syntax for `update()`; they just say 'use Django syntax', extremely unhelpful.
* Update pymongo to 2.8 / 2.9. Same error. 3.0 is unfortunately incompatible with our codebase.
* Update mongoengine to 0.9 / 0.10. Same error.

System:

* pymongo 2.7
* mongoengine 0.8.8
* python 3.3.6
* mongo 2.4.9
* Mac OS X 10.10.5

A. Jesse Jiryu Davis

unread,
Sep 16, 2015, 3:50:52 AM9/16/15
to mongodb-user
Hi Andrew. This is quirky, but reading MongoEngine's source I see that "update" is declared:

    def update(self, upsert=False, multi=True, write_concern=None,
               full_result=False, **update):

Since "upsert" is the first argument in the list, the Python interpreter considers the first argument you pass, { '_id': contest }, to be the value for "upsert", and complains later that you are also trying to pass the keyword argument "upsert=False", no matter how you do it.

Based on this example in the tutorial I think what you want is (untested):

ShoutletContestConfig.objects(id=contest).update(
    config__submission__twitter_retweet_last_backfilled=backfill_date)

"upsert" will default to False in that case, but you could set it explicitly as a kwarg at the end:

ShoutletContestConfig.objects(id=contest).update(
    config__submission__twitter_retweet_last_backfilled=backfill_date, upsert=False)

Or as the first positional argument:

ShoutletContestConfig.objects(id=contest).update(
    False, config__submission__twitter_retweet_last_backfilled=backfill_date)

Let me know if that works, I'm not a MongoEngine user myself.
Reply all
Reply to author
Forward
0 new messages