2012-09-12 24 views
9

私はmongoengineの構文に苦しんでいます。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 

を持っている...それはとself.postsに存在するかどうmy_methodするに渡された郵便物で、私は既存のポストを更新したいですUIDにマッチするか、そうでない場合はself.postsにプッシュします。

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

答えて

15

いいえリストフィールドでは、1つのクエリのリストにupsertを実行することはできません。 postを変更したので、$addToSetはうまく動作しません。この - 私たちは更新しようとすると、それが存在しない場合、我々はリストにプッシュまず

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文を使用してオブジェクト全体を設定できます。コストはフィードデータを取得するための追加のクエリになります。

+0

完璧、ありがとう! –

+0

'' mongoengine'を使って@Rossこの応答を得る方法 'WriteResult({" nMatched ":0、" nUpserted ":0、" nModified ":0})?その商品が見つかったかどうかチェックしたい。ありがとう –

0
Feed.objects.filter(posts__uid=post.uid).\ 
      update_one(push__posts__S__comments='comment demo') 
関連する問題