Исправьте количества и обеспечьте соблюдение правил каталога

MongoDBBeginner
Практиковаться сейчас

Введение

FIELDNOTE согласовал, какие унаследованные строковые количества означают достоверные числа. Теперь нужен пригодный каталог, сохраняющий эти значения и отклоняющий неопределённые будущие записи. Один валидатор не очищает существующие записи, а преобразование всех значений может уничтожить полезные различия или выдумать количества.

Вы поместите неопределённые оригиналы в карантин, преобразуете только утверждённые скалярные строки и добавите настоящий валидатор MongoDB. Вы также создадите и обновите обычный допустимый комплект, чтобы магазин продолжал работу. Сначала выполните Классифицируйте записи оборудования и поместите неопределённые в карантин: здесь используются политика документов, скрипт сохранения оригиналов, синтаксис терминала и файлов и различия BSON из этого занятия. Это занятие начинается независимо с нового смешанного каталога и копий двух завершённых исходных файлов. Файлы, данные или работающие процессы предыдущего окружения не требуются. Используйте Terminal на протяжении всей работы; MongoDB и оболочка подготовлены. Длительность — оценка автора.

Создайте repair.js и enforce.js в /home/labex/project/catalog-desk. Вы можете изучить и сохранить предоставленные policy.js и quarantine.js; эквивалентные реализации политики и миграции должны соблюдать тот же контракт. Сохраните все исходные ID, посторонние поля, исходные типы int/long, полные неопределённые оригиналы в карантине, идентичность коллекций и предоставленные инструменты. Только утверждённые строки в stock.available могут стать целочисленными количествами. Добавьте KIT-901 как указано и уменьшите его количество один раз; отклонённого KIT-902 быть не должно. Не удаляйте и не пересоздавайте коллекции, не заменяйте неизвестные количества нулём, не перезаписывайте архивные оригиналы и не запрещайте допустимые дополнительные поля. Работа последовательна, без конкурирующих записей, и не даёт транзакции через всю миграцию.

Преобразуйте только утверждённые строковые количества

На этом шаге вы удалите неопределённые записи через процесс с сохранением оригиналов и преобразуете только согласованные строковые представления. Начните во вкладке Terminal. Перейдите в подготовленный рабочий каталог этого занятия:

cd /home/labex/project/catalog-desk

Прочитайте обычную запись и изучите типы нового каталога:

./catalog show KIT-101
./catalog types

Начальные данные снова смешанные: у KIT-101 Int32 12, у KIT-102 Long ноль, у KIT-103/KIT-104 утверждённые строки, а KIT-105–KIT-111 требуют проверки. Это независимое занятие, поэтому успешная миграция предыдущего не скопирована в базу данных.

cat без перенаправления печатает сохранённый файл, а не меняет его. Изучите предоставленные политику и скрипт карантина из предыдущей пошаговой работы:

cat policy.js
cat quarantine.js

Селектор valid принимает непустые строковые ID и имена и скалярные количества BSON int/long от 0 до 50. repairable принимает ту же структуру только с каноническими десятичными строками в этом диапазоне. bad выбирает не подходящее ни одному из них. Скрипт карантина сохраняет типы BSON, полные исходные документы и проверяет существующую копию перед удалением соответствующего активного источника. В этом контролируемом сценарии его безопасно повторять, и он отклоняет конфликтующую старую копию, а не перезаписывает её.

Изучите фактические группы, затем запустите именно эти сохранённые исходные файлы:

./catalog classify policy.js
./catalog run policy.js quarantine.js

Прочитайте оставшиеся активные записи и сохранённые оригиналы:

./catalog show
./catalog archive

Активными должны остаться только KIT-101–KIT-104. Их количества всё ещё имеют типы int, long, string и string соответственно. KIT-105–KIT-111 относятся к карантину с полными оригиналами, включая различия отсутствия, null, массива и Double и дополнительные поля проверки поставщиком. Никакое количество пока не угадывалось и не преобразовывалось.

Теперь сохраните конвейер обновления. Обычный документ обновления использует операторы обновления; массив ниже вместо этого содержит стадии агрегирования, вычисляющие каждое меняемое поле из текущего значения этой записи. $set в этом конвейере задаёт указанное поле, а $toInt: "$stock.available" читает текущее вложенное количество и преобразует утверждённую строку в BSON Int32. Строка с префиксом доллара — ссылка на поле, а не буквальный текст для сохранения. Путь назначения с точкой "stock.available" обновляет только это вложенное поле, сохраняя stock.rack и каждое другое исходное поле.

updateMany действует только на записи, выбранные repairable. Уже допустимые int/long не подходят строковому селектору и сохраняют исходные типы. Без правильного фильтра преобразование может остановиться на непреобразуемом значении после изменения предыдущих записей; всё многодокументное обновление не атомарно. Использование onError: 0 или onNull: 0 выдумало бы количество и нарушило задание. В этом подготовленном последовательном сценарии нет конкурирующих записей.

Here-document REPAIR записывает полный файл буквально, как в предыдущем занятии:

cat > repair.js <<'REPAIR'
printjson(db.equipment.updateMany(
  repairable,
  [{$set: {"stock.available": {$toInt: "$stock.available"}}}]
));
REPAIR

Сначала выполните политику, чтобы имена селекторов были доступны, затем сохранённое обновление:

./catalog run policy.js repair.js

Найдите matchedCount: 2 и modifiedCount: 2. Проверьте фактические документы и типы, поскольку одного числа изменений недостаточно для доказательства сохранности:

./catalog show
./catalog types

Теперь у KIT-103 Int32 12, у KIT-104 Int32 ноль. KIT-102 должен всё ещё иметь исходный ноль типа long. Все исходные имена, места хранения, поля поставщиков и ID сохранены. Изучите оставшуюся классификацию:

./catalog classify policy.js

Все четыре активные записи должны быть в valid; обе другие группы — пустыми. Обратите внимание, почему перед этим аудитом был нужен карантин: одно преобразование не удалило бы null, отсутствующие или неопределённые значения.

Повторите утверждённое преобразование:

./catalog run policy.js repair.js

Оба счётчика теперь должны быть нулевыми, поскольку утверждённых строк не осталось. Это идемпотентное преобразование; оно не означает, что любая возможная ошибка базы данных автоматически откатывает предыдущие записи. При синтаксической ошибке файла перепишите полный here-document и запустите снова. При неверном имени файла используйте ls и исправьте его; сохраните существующую базу вместо сброса.

Проверяйте будущие записи, сохраняя обычную работу

На этом шаге вы примените принятый контракт документов к будущим штатным записям MongoDB и докажете, что магазин всё ещё может создавать и обновлять допустимый комплект. Начните во вкладке Terminal, в /home/labex/project/catalog-desk.

Команда MongoDB collMod меняет параметры существующей коллекции. Здесь она подключает тот же селектор valid как валидатор. validationLevel: "strict" проверяет вставки и обновления, включая обновление записи, которая уже была недопустимой. validationAction: "error" отклоняет нарушающую правила запись. moderate может освобождать от проверки обновления уже недопустимых записей; warn может разрешать нарушающую запись с её журналированием. Ни один из этих вариантов не даёт требуемый здесь строгий контракт будущих записей.

Подключение валидатора — не очистка задним числом: collMod может завершиться успешно, пока недопустимые существующие записи остаются. Поэтому сначала вы поместили неопределённые оригиналы в карантин, преобразовали только утверждённые строки и проверили активный каталог. Успешный ответ команды свидетельствует об изменении параметра; настоящая принятая или отклонённая запись свидетельствует о его действии.

Сохраните штатную команду. db.runCommand выполняет её в текущей базе данных курса, а printjson показывает фактический ответ:

cat > enforce.js <<'ENFORCE'
printjson(db.runCommand({
  collMod: "equipment",
  validator: valid,
  validationLevel: "strict",
  validationAction: "error"
}));
ENFORCE

Запустите политику и этот новый файл без изменений:

./catalog run policy.js enforce.js

Ожидается ok: 1. Прочитайте настоящие параметры коллекции:

./catalog status

Вывод должен включать валидатор equipment с validationLevel: "strict" и validationAction: "error". Это средство чтения также сообщает настоящие версии сервера и оболочки и выбранную базу; оно не создаёт за вас успешный результат валидации.

Попробуйте одну неопределённую будущую вставку через обычное соединение с правом записи. invalid-text передаёт настоящий комплект с количеством "12 kits". Ожидайте ненулевой код и Document failed validation, а не ошибку соединения:

./catalog invalid-text KIT-902

Убедитесь, что не сохранилась частичная новая запись:

./catalog show KIT-902

Результат должен быть []. Отклонённая запись не превратила неизвестный текст в ноль и не создала заменяющую запись карантина. Будущие недопустимые записи отклоняются; записи карантина документируют прежние унаследованные данные.

Теперь создайте допустимый новый комплект. new ID COUNT передаёт документ с количеством Int32, местом хранения и полями поставщика. Используйте согласованный новый ID KIT-901 и начальное количество 4:

./catalog new KIT-901 4

Найдите подтверждённую вставку KIT-901. Его дополнительные поля места хранения и поставщика должны быть разрешены. use ID COUNT выполняет настоящее условное обновление: уменьшает доступное количество только при достаточном числе единиц у этой записи. Используйте одну единицу:

./catalog use KIT-901 1

Ожидаются matchedCount: 1 и modifiedCount: 1. Прочитайте фактический результат:

./catalog show KIT-901

KIT-901 должен сохранить name, место хранения NEW и поставщика LOCAL, с доступным количеством Int32 3. Исходные четыре очищенные записи и все оригиналы карантина должны остаться неизменными. Строгий целочисленный контракт всё ещё допускает известный ноль, включительную верхнюю границу, существующие количества long, посторонние поля и обычные допустимые обновления.

Не повторяйте new после успеха: уникальный _id вызвал бы ошибку дублирующегося ключа. Не повторяйте use, если не намерены уменьшить количество ещё раз. Сохранённый скрипт исправления имеет идемпотентный предикат только для строк; обычное действие использования остатков намеренно меняет рабочее состояние каждый раз. Если вы случайно снова уменьшили KIT-901, задание позволяет восстановить только этот новый комплект до требуемого итогового количества. Используйте небольшое сохранённое штатное обновление с тем же синтаксисом here-document, затем изучите результат. Int32(3) явно создаёт 32-битное целое BSON со значением 3:

cat > restore-new-kit.js <<'RESTORE'
printjson(db.equipment.updateOne({_id: "KIT-901"}, {$set: {"stock.available": Int32(3)}}));
RESTORE
./catalog run restore-new-kit.js
./catalog show KIT-901

Это восстановление затрагивает только ваш новый комплект и должно оставить требуемое итоговое количество 3. Это не способ перезаписи унаследованных оригиналов или оригиналов карантина. Ваши файлы политики, карантина, исправления и проверки теперь выражают полную контролируемую миграцию для повторного использования, а живой каталог показывает, что обычная допустимая работа остаётся возможной.

Резюме

Вы преобразовали утверждённые строковые количества, не заменяя другие вложенные поля и не меняя уже допустимые числовые типы. Вы проверили очищенный каталог, обеспечили его контракт валидацией strict/error, увидели настоящий отказ недопустимой записи и выполнили обычные допустимые вставку и обновление. Сохранённые скрипты и оригиналы поддерживают контролируемый повторяемый процесс обслуживания; они не обещают атомарную миграцию всего каталога или безопасность от конкурирующих записей.