Nein, mit Listenfeld können Sie in einer einzigen Abfrage kein Upsert in eine Liste durchführen. $addToSet
funktioniert nicht, da du den post
geändert hast Sie können also nicht übereinstimmen. Sie können dies runden, aber es erzeugt eine Race-Bedingung, bei der es ein kleines Zeitfenster für Fehler gibt, z. B.:
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)
Zuerst versuchen wir zu aktualisieren, und wenn es nicht existiert, verschieben wir es auf die Liste – hier gibt es ein Zeitfenster, in dem ein anderer Prozess ausgeführt und möglicherweise den post
übertragen kann auf der Liste.
Das Risiko mag akzeptabel sein, aber realistisch gesehen denke ich, dass es besser ist, Ihr Schema zu ändern und möglicherweise Post
aufzuteilen in eine eigene Sammlung. Dann können Sie eine Update-Anweisung verwenden und das gesamte Objekt festlegen. Die Kosten sind eine zusätzliche Abfrage zum Abrufen der Feed-Daten.