#mongodb #mongodb-query
Вопрос:
Я немного бегаю по кругу здесь и был бы признателен за некоторую помощь. То, что я хочу сделать, — это либо обновить, либо создать вложенный объект, содержащийся в массиве, в зависимости от того, существует ли этот объект.
У меня есть коллекция пользователей, и пользовательский документ имеет следующую структуру:
{
schema_version: 1,
display_name: 'xxxxxx',
email: 'xxxxxx',
email_verified:'xxxxxx',
...
custom_data: {
stripe_id: 'xxx',
subscriptions: [{
subscription_id: xxxx,
....
}],
...
},
}
В вызовах webhook от Stripe я получаю объект подписки с a subscription_id
и a stripe_id
.
Что я хочу сделать, так это проверить, subscription_id
существует ли, если да, обновите документ, если нет, то создайте документ в массиве подписок для пользовательского документа, где stripe_id
совпадения.
Если я сделаю что-то в духе:
db.collection.update(
{subscription_id: subscription.id},
{ $set: { 'custom_data.subscriptions': subscriptionData } },
{ upsert: true }
)
Проблема в том, что я создаю объекты подписки, не привязанные к моему пользовательскому документу, где stripeID совпадает.
С другой стороны, если я сделаю что-то подобное:
db.collection.update(
{'custom_data.stripe_id': stripe_id},
{ $set: { 'custom_data.subscriptions': subscriptionData } },
{ upsert: true }
)
Я потенциально закончу тем, что создам обманщиков в массиве подписок, когда на самом деле я хотел бы обновить существующий объект, где совпадает subscription_id.
Есть ли какой-либо способ сделать это в одном запросе с Mongo, или мне придется прибегнуть к использованию 2 запросов в операторе if?
Заранее спасибо за любые разъяснения по этому поводу.
Комментарии:
1. Вы можете обновить элемент массива, если он существует, или вставить новый элемент — вы можете сделать это за одну операцию обновления. См. раздел об обновлениях с помощью конвейера агрегации. Также ищите похожие сообщения.
Ответ №1:
Вы можете выполнить следующие действия с помощью конвейера агрегации:
$match
с$or
условием поискаcustom_data.subscriptions.subscription_id
илиcustom_data.stripe_id
$addFields
с$map
для условного обновления объекта подписки при сопоставлении$addFields
с$setUnion
, чтобы вставить запись объекта входящей подписки для случая вставки$merge
чтобы обновить обратно в исходную коллекцию
Вот игровая площадка Монго для вашей справки.