How to Do An Atomic Update on an EmbeddedDocument in a ListField in MongoEngine?

折月煮酒 提交于 2019-12-24 01:54:26

问题


I've found some similar questions on StackOverflow, but nothing that addresses what I'm looking for, so any help would be appreciated.

My models:

class BlogPost(EmbeddedDocument):
  title = StringField(required=True)
  blog_url = StringField(required=True, unique=True)
  content = StringField()
  turned_into_bitly_link = BooleanField(default=False)

class Person(Document):
  name = StringField
  blog_posts = ListField(EmbeddedDocumentField(BlogPost), default=list)

For each blogpost.blog_url, I query the Bitly API to see if the url has been shortened. What I need to be able to do is match up the data I get back from Bitly with the appropriate blogpost in my database. The objects I get back from Bitly contain a url field that I need to use to match up and update the appropriate blogpost in my database. Should also say that I send a batch of blog_urls to Bitly at a time, one-by one is not an option.

Given a set of blog_posts and Bitly objects all stemming from a given individual: person = Person.objects.get(name__exact='BobSmith')

How can I select the specific blog_post embedded in my Person object by the unique URL field?

As a stopgap, I suppose I could iterate over the blog_posts in my person object, and if the blog_post.url matches the URL in my Bitly object, I can then update the turned_into_bitly_link field, but I'm not sure this is the most efficient way of going about this.

Hope this makes sense. I'm happy to clarify, and thanks in advance for any advice.

Ben


回答1:


You can use the positional operator to update the matched embedded document.

Heres an example from the tests (https://github.com/MongoEngine/mongoengine/blob/master/tests/test_queryset.py#L313)

def test_update_using_positional_operator(self):
    """Ensure that the list fields can be updated using the positional
    operator."""

    class Comment(EmbeddedDocument):
        by = StringField()
        votes = IntField()

    class BlogPost(Document):
        title = StringField()
        comments = ListField(EmbeddedDocumentField(Comment))

    BlogPost.drop_collection()

    c1 = Comment(by="joe", votes=3)
    c2 = Comment(by="jane", votes=7)

    BlogPost(title="ABC", comments=[c1, c2]).save()

    BlogPost.objects(comments__by="jane").update(inc__comments__S__votes=1)

    post = BlogPost.objects.first()
    self.assertEquals(post.comments[1].by, 'jane')
    self.assertEquals(post.comments[1].votes, 8)


来源:https://stackoverflow.com/questions/10922956/how-to-do-an-atomic-update-on-an-embeddeddocument-in-a-listfield-in-mongoengine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!