user2264738
user2264738

Reputation: 322

Mongoengine Log events specific to a document in a collection to another collection with new fields

In my project I'm using Mongodb with mongoengine ORM(Python),

MongoDB shell version: 3.0.3

pymongo==3.1.1

mongoengine==0.10.1

I Wanted to track events happening to a collection to a log_collection, with original documents fields plus some new fields.

That is when a document in the Original collection is getting updated with an event, there would be a new document added to the log_collection.

class Original(DynamicDocument):
    identifier = StringField(required=True, unique=True, primary_key=True)
    field1 = StringField()

class LogEvents(DynamicDocument):
    pass

For this I tried to make use mongoengeine switch_collection

col = Original.objects.get(id=some_id)
col.switch_collection('log_events', False)
col.new_field = "new_field"
col.save()

When we call the col.save() ,

1) it update to the log_events collection with the primary key field (_id) of the original document, so we cannot log the multiple events pertaining to the same document in the Original collection.

2) Even if we change the primary key field(_id), to a new value and save(),

col = Original.objects.get(id=some_id)
col.switch_collection('log_events', False)
col.id=<new-id>
col.new_field = "new_field"
col.save()

Then as it calls the save method of the Original collection, and there are unique indexes with multiple fields on the Original collection, its not possible to save to DB.

  1. Is there any easy way to log events to the LogEvents collection without much hassle.
  2. What is the use of cascade and cascade_kwargs options with the save method, how can we make use of it..?

Upvotes: 1

Views: 231

Answers (2)

lesingerouge
lesingerouge

Reputation: 1168

A simple option for your kind of problem would be to overload the save() method of the Original class. Something like this:

class Original(DynamicDocument):
    identifier = StringField(required=True, unique=True, primary_key=True)
    field1 = StringField()

    def save(self, value):
        #save the document in its normal collections
        super(Original, self).save() 
        #switch collection and save a new event
        with switch_collection(Original, 'log_events') as Events:
            self.new_field = value
            #let's give it a new id
            self.identifier = 'something new'
            super(Events, self).save()

Now everytime you save an instance of Original, you can pass in a value to be saved separately in the log_events collection. With a bit of creative work you can pass more than one value or set more than one attribute.

Upvotes: 0

J&#233;r&#244;me
J&#233;r&#244;me

Reputation: 14674

  1. What is the use of cascade and cascade_kwargs options with the save method, how can we make use of it..?

Mongoengine Docs:

cascade_save(*args, **kwargs)

Recursively saves any references / generic references on the document

Basically, this determines whether or not referenced documents are automatically saved when saving referencer document.

I don't think it is related to your issue.

Upvotes: 0

Related Questions