Разница между набором с {merge: true} и обновлением

116

В Cloud Firestore есть три операции записи:

1) добавить

2) set (набор)

3) update

В документации говорится, что использование set(object, {merge: true})объединит объект с существующим.

То же самое происходит при использовании. update(object) Итак, в чем разница, если она есть? Кажется странным, что Google будет дублировать логику.

ZuzEL
источник

Ответы:

264

Как я понял разницу:

  • setбез merge- перезапишет документ или создаст его, если он еще не существует

  • setwith mergeобновит поля в документе или создаст его, если он не существует

  • update обновит поля, но не удастся, если документ не существует

  • create создаст документ, но завершится неудачно, если документ уже существует

Также есть разница в типах данных, которые вы предоставляете setи update.

Потому что setвам всегда нужно предоставлять данные в форме документа:

set(
  {a: {b: {c: true}}},
  {merge: true}
)

С помощью updateвы также можете использовать пути к полям для обновления вложенных значений:

update({
  'a.b.c': true
})
Scarygami
источник
1
но где вы нашли createметод в API?
ZuzEL 06
2
cloud.google.com/nodejs/docs/reference/firestore/0.8.x/… для node.js. Кажется, в веб-API такого метода нет. Не был уверен, на какой платформе вы находитесь :)
Scarygami
10
Еще одно различие, которое вы можете упомянуть, - это то, что setработает с данными в форме документа, где updateпринимает пары путь к полю и значение. Это означает, что вы можете вносить изменения в глубоко вложенные значения с помощью updateболее громоздких set. Например: set({a: {b: {c: true}}}, {merge: true})против update('a.b.c', true).
Гил Гилберт
Если я хочу обновить значение в документе, имеет смысл обновить уже существующие документы, поэтому я думаю, что set + mergeall не так полезен, потому что он создаст его, документ не существует,
Джон Балвин Ариас,
Если данные, которые вы предоставляете команде set, имеют поле, которое имеет значение NULL, будет ли оно установлено в значение NULL, если оно уже присутствует в базе данных, или оно останется в покое?
user1023110
71

Еще одно различие (расширение ответа Scarygami) между «набором слиянием» и «обновлением» заключается в работе с вложенными значениями.

если у вас есть документ с такой структурой:

 {
   "friends": {
     "friend-uid-1": true,
     "friend-uid-2": true,
   }
 }

и хочу добавить {"friend-uid-3" : true}

используя это:

db.collection('users').doc('random-id').set({ "friends": { "friend-uid-3": true } },{merge:true})

приведет к этим данным:

 {
   "friends": {
     "friend-uid-1": true,
     "friend-uid-2": true,
     "friend-uid-3": true
   }
 }

однако updateиспользуя это:

db.collection('users').doc('random-id').update({ "friends": { "friend-uid-3": true } })

приведет к этим данным:

 `{
   "friends": {
     "friend-uid-3": true
   }
 }`
Финли Перси
источник
1
Вы сами пробовали это проверить? В документации есть раздел: «Чтобы обновить некоторые поля документа без перезаписи всего документа, используйте метод update () ...» ссылка
Финли Перси
2
Я понял. Раньше я пробовал это только с массивом. Где я хотел добавить объект в массив, и все было перезаписано для этого массива. Он не работает с полями, содержащими массив ... он поддерживает документы.
ravo10 06
1
Просто пришел к такому же выводу после тестов. Я надеюсь, что они добавят опцию, имеющую такой же эффект, что { merge: true }и функция обновления.
Johnride
1
Спасибо за этот ответ! Примеры, хотя и простые, сделали его более чистым, чем принятый ответ, который лучше подходит для моего варианта использования.
naiveai
2
Чтобы избежать перезаписи данных во вложенных полях (как в ответе выше) при использовании update, вы можете использовать точечную нотацию . Поведение перезаписи updateбудет другим, если вы используете / не используете точечную нотацию.
Тедсковский
7

Для документов: https://firebase.google.com/docs/firestore/manage-data/add-data#update_fields_in_nested_objects

Точечная запись позволяет обновлять одно вложенное поле без перезаписи другого вложенного поля. Если вы обновите вложенное поле без записи через точку, вы перезапишете все поле карты.

Как указано выше, это заменяет всю структуру друзей.

db.collection('users').doc('random-id').update({
    "friends": {
        "friend-uid-3": true
    }
})

Это не так.

db.collection('users').doc('random-id').update({
    "friends.friend-uid-3": true
})
CodeManDan
источник