Updating a list of embedded documents in mongoengine

▼魔方 西西 提交于 2019-12-03 06:53:15

问题


I'm struggling with mongoengine syntax.

I have the following models...

class Post(EmbeddedDocument):
    uid = StringField(required=True)
    text = StringField(required=True)
    when = DateTimeField(required=True)


class Feed(Document):
    label = StringField(required=True)
    feed_url = StringField(required=True)
    posts = ListField(EmbeddedDocumentField(Post))

    def my_method(self, post):
        pass

... and with the post object passed into to my_method, I'd like to update an existing post if it exists in self.posts with a matching uid, or push to self.posts if not.

Is there syntax to do that in one call in mongoengine?


回答1:


No with list field you cannot do an upsert into a list in a single query. $addToSet wont work as you've changed the post so you cant match. You can code round this but it does create a race condition where there is a small window of opportunity for error eg:

    class Post(EmbeddedDocument):
        uid = StringField(required=True)
        text = StringField(required=True)

    class Feed(Document):
        label = StringField(required=True)
        feed_url = StringField(required=True)
        posts = ListField(EmbeddedDocumentField(Post))

    Feed.drop_collection()

    Feed(
        label="label",
        feed_url="www.feed.com"
    ).save()

    post = Post(uid='1', text="hi")
    updated = Feed.objects(posts__uid=post.uid).update_one(set__posts__S=post)
    if not updated:
        Feed.objects.update_one(push__posts=post)

First we try to update and if it doesn't exist we push to the list - this is where there is a window of opportunity for another process to run and potentially push the post on the list.

The risk might be acceptable but realistically, I think changing your schema is better, potentially splitting Post out into its own collection. Then you can use an update statement and set the whole object. The cost will be an extra query to get the feed data.




回答2:


Feed.objects.filter(posts__uid=post.uid).\
          update_one(push__posts__S__comments='comment demo')


来源:https://stackoverflow.com/questions/12387478/updating-a-list-of-embedded-documents-in-mongoengine

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