Обновление условий MongoDB

#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:

Вы можете выполнить следующие действия с помощью конвейера агрегации:

  1. $match с $or условием поиска custom_data.subscriptions.subscription_id или custom_data.stripe_id
  2. $addFields с $map для условного обновления объекта подписки при сопоставлении
  3. $addFields с $setUnion , чтобы вставить запись объекта входящей подписки для случая вставки
  4. $merge чтобы обновить обратно в исходную коллекцию

Вот игровая площадка Монго для вашей справки.