Non, avec le champ de liste, vous ne pouvez pas effectuer d'upsert dans une liste en une seule requête. $addToSet
ne fonctionnera pas car vous avez changé le post
donc vous ne pouvez pas correspondre. Vous pouvez coder autour de cela, mais cela crée une condition de concurrence où il y a une petite fenêtre d'opportunité d'erreur, par exemple :
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)
Nous essayons d'abord de mettre à jour et s'il n'existe pas, nous poussons vers la liste - c'est là qu'il y a une fenêtre d'opportunité pour qu'un autre processus s'exécute et potentiellement pousse le post
sur la liste.
Le risque peut être acceptable mais de manière réaliste, je pense que changer votre schéma est préférable, en divisant potentiellement Post
dans sa propre collection. Ensuite, vous pouvez utiliser une instruction de mise à jour et définir l'objet entier. Le coût sera une requête supplémentaire pour obtenir les données du flux.