Mongoengine : How to update specific fields of an existing document?

shuttlesworthNEO picture shuttlesworthNEO · Jul 10, 2018 · Viewed 10.4k times · Source

I have an existing mongo document which has been exposed over a REST API. The API request will contain certain fields from the document which either needs to be updated with new values or insert new values in them if the field is null. How to perform the update on fields of an existing mongoengine document? I'm using marshmallow-mongoengine for serialization on flask.

The problem that I'm facing is that if a certain field is missing in the request payload, on calling update with the remaining fields as kwargs leads to setting the missing fields as None. How can update or insert only the fields given in the payload?

Answer

ChampR picture ChampR · Jul 27, 2018

Joseph's answer is OK. But another answer wont hurt eh!

Here's how i updated my document using flask-mongoengine

Actual code :

Game.objects(id = _id).update(
        set__kickoff = request_json.get('kickoff'),
        set__gameid = request_json.get('gameid'),
        set__home_team = request_json.get('home_team'),
        set__away_team = request_json.get('away_team'),
        set__home_win = request_json.get('home_win'),
        set__draw = request_json.get('draw'),
        set__away_win = request_json.get('away_win'),
        set__sport = request_json.get('sport')
        )

Game class : 

    import datetime
    flask_mongoengine import BaseQuerySet, MongoEngine
    db = MongoEngine()

    class Game(db.Document):
    kickoff  = db.DateTimeField(required=True)
    added_on  = db.DateTimeField(default=datetime.datetime.utcnow)
    gameid = db.FloatField(required=True)     
    home_team = db.StringField(required=True)
    home_win = db.FloatField(required=True)    
    draw = db.FloatField(required=True)
    away_win = db.FloatField(required=True)
    away_team = db.StringField(required=True)
    sport = db.StringField(required=True) 
    meta = {
        'collection':'games',
        'queryset_class': BaseQuerySet
    }

PS : Remember to indent the code in python

Additionally I noticed you tagged Marshmallow in your question. Here, a sample derived from their official git repo here

First we need a Mongoengine Document:

import mongoengine as me

class Task(me.EmbeddedDocument):
    content = me.StringField(required=True)
    priority = me.IntField(default=1)


class User(me.Document):
    name = me.StringField()
    password = me.StringField(required=True)
    email = me.StringField()
    tasks = me.ListField(me.EmbeddedDocumentField(Task))

Great ! Now it's time for the Marshmallow Schema. To keep things DRY, we use marshmallow-mongoengine to do the mapping:

import marshmallow_mongoengine as ma

class UserSchema(ma.ModelSchema):
    class Meta:
        model = User

Finally it's time to use our schema to load/dump documents:First let's create a document

user_schema = UserSchema()
u, errors = user_schema.load({"name": "John Doe", "email": 
      "[email protected]", "password": "123456","tasks": [{"content": "Find a 
      proper password"}]})
u.save()

If the document already exists, we can update it using update

u
u2, errors = user_schema.update(u, {"name": "Jacques Faite"})
>>> u2.name
"Jacques Faite"