pythonpython-datetimemongoengine

python & mongoengine, How do I map data to datetime?


I am trying to store temporal data in mongodb with the use of mongoengine. As the date of the data is a primary component, I thought it would be best to map the data to the date. However, when creating the document I receive an error that states Argument to MapField constructor must be a valid field.

I thought a datetime field was a valid field type given that DateTimeField exists in mongoengine. And reading further into the mongoengine Mapfield documentation, I have a suspicion that I am using it wrong.

Is it possible to map data to a datetime field for storage in mongoengine?

code

from datetime import datetime
from mongoengine import StringField, MapField, EmbeddedDocument, FloatField, IntField

class PlaySession(EmbeddedDocument):
    hours_played = FloatField(db_field="hoursPlayed")
    enjoyment = IntField(db_field="enjoyment")
    number_of_players = IntField(db_field="playerNum")


class GameDoc(Document):
    game = StringField(db_field="game")
    console = StringField(db_field="console")
    sessions = MapField(datetime, PlaySession, db_field="sessions")

Solution

  • DateTimeField is a valid type for storing datetime values, but it's not compatible with MapField as a key type. This is why you're getting that error. You can use any of the following alternative solutions instead:

    Solution 1: Use MapField and store datetime objects as strings

    class GameDoc(Document):
        game = StringField(db_field="game")
        console = StringField(db_field="console")
        sessions = MapField(StringField(), PlaySession, db_field="sessions")
    
    # Example
    game = GameDoc(game="Some Game", console="PS5")
    game.sessions[datetime.now().strftime('%Y-%m-%d %H:%M:%S')] = PlaySession(hours_played=3.0, enjoyment=9, number_of_players=4)
    game.save()
    

    Solution 2: Use ListField and a new document model that stores both the session and the date

    class SessionEntry(EmbeddedDocument):
        session_date = DateTimeField(db_field="sessionDate")
        session_data = PlaySession()
    
    class GameDoc(Document):
        game = StringField(db_field="game")
        console = StringField(db_field="console")
        sessions = ListField(EmbeddedDocumentField(SessionEntry), db_field="sessions")