MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Mise à jour d'une liste de documents intégrés dans mongoengine

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.