17

我正在努力使用 mongoengine 语法。

我有以下型号...

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

...并且将 post 对象传递给 my_method,如果现有帖子存在于 self.posts 中且具有匹配的 uid,我想更新它,或者如果不存在则推送到 self.posts。

是否有语法可以在 mongoengine 的一次调用中做到这一点?

4

2 回答 2

18

没有列表字段,您不能在单个查询中对列表进行更新插入。 $addToSet因为你改变了post所以你不能匹配。您可以对此进行编码,但它确实会创建一个竞争条件,其中有一个小的错误机会窗口,例如:

    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)

首先我们尝试更新,如果它不存在,我们推送到列表 - 这是另一个进程运行并可能推送post列表的机会窗口。

风险可能是可以接受的,但实际上,我认为更改架构更好,可能会拆分Post为自己的集合。然后您可以使用更新语句并设置整个对象。成本将是获取提要数据的额外查询。

于 2012-09-13T13:15:32.133 回答
2
Feed.objects.filter(posts__uid=post.uid).\
          update_one(push__posts__S__comments='comment demo')
于 2015-11-16T04:45:44.037 回答