No, con il campo elenco non è possibile eseguire un upsert in un elenco in una singola query. $addToSet
non funzionerà perché hai cambiato il post
quindi non puoi eguagliare. Puoi codificare attorno a questo, ma crea una condizione di gara in cui c'è una piccola finestra di opportunità per l'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)
Per prima cosa proviamo ad aggiornare e, se non esiste, inseriamo l'elenco:è qui che c'è una finestra di opportunità per un altro processo da eseguire e potenzialmente inviare il post
nell'elenco.
Il rischio potrebbe essere accettabile ma realisticamente, penso che cambiare lo schema sia meglio, potenzialmente dividere Post
fuori nella propria collezione. Quindi puoi utilizzare un'istruzione di aggiornamento e impostare l'intero oggetto. Il costo sarà una query aggiuntiva per ottenere i dati del feed.