Nee met een lijstveld kunt u geen upsert doen in een lijst in een enkele zoekopdracht. $addToSet
werkt niet omdat je de post
. hebt gewijzigd dus je kunt niet matchen. Je kunt hier omheen coderen, maar het creëert wel een race-conditie waarbij er een kleine kans is op fouten, bijvoorbeeld:
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)
Eerst proberen we bij te werken en als het niet bestaat, pushen we naar de lijst - dit is waar er een kans is voor een ander proces om uit te voeren en mogelijk de post
te pushen op de lijst.
Het risico is misschien acceptabel, maar realistisch gezien denk ik dat het beter is om je schema te veranderen, waardoor Post
mogelijk wordt gesplitst uit in zijn eigen collectie. Vervolgens kunt u een update-instructie gebruiken en het hele object instellen. De kosten zijn een extra zoekopdracht om de feedgegevens te krijgen.