2012-09-12 12 views
9

Sono in difficoltà con la sintassi di mongoengine.Aggiornamento di un elenco di documenti incorporati in mongoengine

ho i seguenti modelli di ...

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 

... e con l'oggetto messaggio passato in a my_method, vorrei aggiornare un post esistente se esiste nella self.posts con corrispondenza uid, o push to self.posts se non.

C'è sintassi per farlo in una chiamata in mongoengine?

risposta

15

No con campo elenco non è possibile eseguire un inserimento in una lista in una singola query. $addToSet non funzionerà come hai cambiato il post così non puoi eguagliare. È possibile codificare tutto questo, ma lo fa creare una condizione di competizione in cui v'è una piccola finestra di opportunità per errore, ad esempio:

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) 

Prima di tutto cerchiamo di aggiornare e, se non esiste che spingere alla lista - questo è dove c'è una finestra di opportunità per un altro processo da eseguire e potenzialmente spingere lo post nell'elenco.

Il rischio potrebbe essere accettabile ma realisticamente, penso che la modifica degli schemi sia migliore, potenzialmente suddividendo Post nella propria raccolta. Quindi è possibile utilizzare una dichiarazione di aggiornamento e impostare l'intero oggetto. Il costo sarà una query aggiuntiva per ottenere i dati del feed.

+0

Perfetto, grazie! –

+0

@Ross come ottenere questa risposta 'WriteResult ({" nMatched ": 0," nUpserted ": 0," nModified ": 0})' usando 'mongoengine'? Voglio controllare se l'oggetto è stato trovato. Grazie –

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