Nie z polem listy nie można wykonać upsert do listy w jednym zapytaniu. $addToSet
nie będzie działać, ponieważ zmieniłeś post
więc nie możesz dopasować. Możesz to ominąć, ale tworzy to sytuację wyścigu, w której istnieje małe okno możliwości błędu, np.:
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)
Najpierw próbujemy zaktualizować, a jeśli nie istnieje, wypychamy na listę - w tym miejscu pojawia się okno możliwości uruchomienia innego procesu i potencjalnie wypchnięcia post
na liście.
Ryzyko może być akceptowalne, ale realistycznie myślę, że zmiana schematu jest lepsza, potencjalnie dzieląc Post
do własnej kolekcji. Następnie możesz użyć instrukcji aktualizacji i ustawić cały obiekt. Kosztem będzie dodatkowe zapytanie o dane kanału.