Não, com o campo de lista, você não pode fazer um upsert em uma lista em uma única consulta.
$addToSet
não funcionará porque você alterou o post
então você não pode combinar. Você pode codificar em volta disso, mas cria uma condição de corrida em que há uma pequena janela de oportunidade para erro, por exemplo: 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)
Primeiro, tentamos atualizar e, se não existir, enviamos para a lista - é aqui que há uma janela de oportunidade para que outro processo seja executado e, potencialmente, envie o
post
na lista. O risco pode ser aceitável, mas, realisticamente, acho que é melhor alterar seu esquema, potencialmente dividindo
Post
em sua própria coleção. Então você pode usar uma instrução de atualização e definir todo o objeto. O custo será uma consulta extra para obter os dados do feed.