при обновлении документа firestore, если он будет иметь такую структуру:
{
item1: {...},
item2:{...},
item3:{...},
...
item1000:{...}
}
Это таблица, пользователи могут видеть её целиком или частично. Также каждый элемент может редактироваться, причем разные элементы могут редактировать одновременно много пользователей (в системе будет работать порядка 20-30 человек одновременно). Один и тот элемент редактироваться одновременно несколькими людьми не будет.
Обновление данных происходит вот так:
await updateDoc(docRef, { [data?.id]: data });
Будут конфликты. Будут проблемы с индеком. Будут проблемы с размером документа.
С размером проблем не будет, он гарантировано будет меньше того что в лимитах, это учтено. Что за проблемы с индексами?
Меньше 1 Mb?
да, есть ограничение в 0.8мб, потом создаётся новый документ
По умолчанию, для каждого поля строится индекс.
так, а проблема в чём может быть?
Для одного поля это можно отключить. Для больше 1 полей уже сложнее.
В целом, аккумулировать данные можно, если они фиксированного размера в одном поле и устраивает скорость записи 1/сек.
На документ целиком ограничение записи 1/сек или на отдельный елемент в нём, как в моём случае это строка таблицы?
Это ограничение можно обойти, но это не так просто и тоже есть ограничения.
Я сделал тестовую функцию, которая просто делает 30 запросов практически одновременно. Так вот, в базу они все записываются
Вы последовательно записываете.
последовательно, но точно быстрее чем 1 запись в секунду
1 секунда это худьший случай.
Просто если у вас несколько клиентов, то последовательной записи не будет.
Запустите параллельно.
получиться, что при параллельном обновлении двух разных элементов документа, есть риск что одно из обновлений не сохранится?
как тогда лучше поступить мне?
В транзакции читаете документ и запускаете его обновление.
вот это ? https://firebase.google.com/docs/firestore/manage-data/transactions?authuser=0
Сделал по документации: try { await runTransaction(db, async (transaction) => { const sfDoc = await transaction.get(docRefFinal); if (!sfDoc.exists()) { throw "Document does not exist!"; } transaction.update(docRefFinal, { [data?.id]: newData }); }); } catch (e) {} Не совсем понимаю, нужно ли мне использовать const sfDoc = await transaction.get(docRefFinal)? Сам по себе код работает сейчас так же, данные изменяются корректно в базе.
try { … } catch (e) { console.error(e) }
Ну да, то же что у меня. При обновлении строки пользователем, я передаю её целиком в документ. Мне только необходимо что бы функция записи, эти данные записала в момент когда других транзакций не было и обновление документа происходит в его последней версии. Как я понял тот код что я сделал решает это, или я ошибаюсь?
У вас catch блок пустой, вы ошибки не увидите никогда.
С этим мне всё понятно) Я пока не могу понять будет ли мой код (до момента возможной ошибки) работать так как мне нужно.
Вы параллельно его запустили?
ещё нет, сейчас проверю
Запустил параллельно, получаю кучу предупреждений в консоль, но данные записывает корректно, но чуть медленнее.
Да, похоже не правду. По умолчанию, транзакция повторяется в случае неудачи до 5 раз.
То есть, после 5 раз я получу не предупреждение а уже какую-то ошибку?
Фух.. спасибо большое за помощь) Надеюсь это будет работать в итоге)
https://firebase.google.com/docs/firestore/query-data/index-overview#single-field_index_exemptions
{ records: { item1: {...}, item2: {...}, item3: {...}, ... item1000: {...} } }
только я не знаю названий item1,item2...и т.д., это уникальные идентификаторы которые генерирует база данных generateId() { const newId = push(child(ref(db), 'generatorIds')).key; return newId; },
Обсуждают сегодня