Skip to content

Instantly share code, notes, and snippets.

@pingwping
Last active March 6, 2023 18:35
Show Gist options
  • Save pingwping/92219a8a1e9d44e1dd8a to your computer and use it in GitHub Desktop.
Save pingwping/92219a8a1e9d44e1dd8a to your computer and use it in GitHub Desktop.
Create and update embedded documents with MongoEngine
# REF: http://www.quora.com/How-do-I-create-and-update-embedded-documents-with-MongoEngine
class Comment(EmbeddedDocument):
content = StringField()
name = StringField(max_length=120)
class Post(Document):
title = StringField(max_length=120, required=True)
author = StringField(required=True)
tags = ListField(StringField(max_length=30))
comments = ListField(EmbeddedDocumentField(Comment))
# Create a post:
post = Post(title="Quora rocks", author="Ross", tags=['tutorial', 'how-to'])
post.save()
# Find a post
post = Post.objects.find(title="Quora rocks").first()
# Create a new comment
comment = Comment(content="Great post!", name="john")
# Add to comments list and save
post.comments.append(comment)
post.save()
# To editing existing comments you can use atomic updates[1] or simply change the comment and call post.save() (this will also do an atomic update).
# Update a comment in place
post = Post.objects.find(title="Quora rocks").first()
post.comments[0].name = "John"
post.save()
# Or update with a set operation
post = Post.objects.find(title="Quora rocks", comment__name="john").update(set__comment__S__name="John)
@damvantai
Copy link

damvantai commented Jul 5, 2019

In Mongoengine version '0.18.2' i don't use Post.objects.find error AttributeError: 'QuerySet' object has no attribute 'find'
I use Post.objects.get will active

@sannithibalaji
Copy link

is there a way to create a comment, while creating post object?

@kenchoong
Copy link

Thanks a lot!!

@lawndoc
Copy link

lawndoc commented Sep 10, 2020

Very clear, thank you! Sometimes I feel like giving a useful example is an art 👍

@mohit-manna
Copy link

can I add ObjectID in comment?

@kenchoong
Copy link

can I add ObjectID in comment?

Get the comment's id by

comment_id = str(comment.id)

@patriciojlg
Copy link

patriciojlg commented Dec 8, 2020

can I add ObjectID in comment?

into class Comment(EmbeddedDocument):
add:
id = ObjectIdField(required = True, default = ObjectId,
unique = True, primary_key = True)

@GabrielBlondeau-Kirby
Copy link

Small update :

post = Post.objects.find(title="Quora rocks", comment__name="john").update(set__comment__S__name="John)

As said in the previous comments:

  • find is now get
  • comment__name should be comments__name

Conclusion:

 post = Post.objects.get(title="Quora rocks", comments__name="john").update(set__comment__S__name="John)

@yugyesh
Copy link

yugyesh commented Jul 16, 2021

comments = ListField(EmbeddedDocumentField(Comment)) causes this error "Invalid embedded document instance provided to an EmbeddedDocumentField:"
Thus, using this resolved my error
comments = ListField(EmbeddedDocumentField('Comment'))

@theflucs
Copy link

theflucs commented Oct 22, 2021

Add to comments list and save

post.comments.append(comment)
post.save()

gives me this error:
ValidationError (Content:61728559370921cb26f21091) (Only lists and tuples may be used in a list field: ['geofences'])

UPDATE
That was a form validation error, caused by not reassigning the field geofences to the newly created list.
Sorry, but If for @pingwping is ok, I leave this comment as it can be of some help for someone else. so if you need, read below.

Where geofences is a Geofence(EmbeddedDocument)
and Content is a Document that has geofences: ListField(EmbeddedDocumentField(Geofence))

I used it like this:

new_gf = Geofence(
      id=str(uuid4()),
      address=geo_address,
      radius=float(geo_radius),
      latitude=float(geo_lat),
      longitude=float(geo_lng)
 )
content = self.get_content_by_id(content_id=content_id)
content.geofences.append(new_gf)
content.save()

The weird thing is, even if I am getting this error, the new_gf is correctly appended to the list, if I try to append a list it doesn't and it gives me error because it doesn't recognise the creation of the Geofence.

Am I doing something wrong?
Anyone noticed it?

Thanks to anyone who can help and thank you @pingwping for the useful gist 💥

@Hercroce
Copy link

Hercroce commented Mar 6, 2023

If you have to update a list of fields based on a JSON or dictionary objects, you could also use the following:

update_comment = {content = "content update",
                  name = "name update"}

post = Post.objects.get(title="Quora rocks")
comment = post.comments.get(name="john")

for key in update:
    comment[key] = update_comment[key]

post.save()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment