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

... my_method に渡された post オブジェクトを使用して、一致する uid を持つ self.posts に存在する場合は既存の投稿を更新し、そうでない場合は self.posts にプッシュします。

mongoengine の 1 回の呼び出しでそれを行う構文はありますか?

4

2 に答える 2

18

いいえ、リスト フィールドでは、単一のクエリでリストに upsert を実行できません。 $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。独自のコレクションに分割される可能性があります。その後、update ステートメントを使用して、オブジェクト全体を設定できます。コストは、フィード データを取得するための追加のクエリになります。

于 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 に答える