MongoDB | Работа в CLI

Тип статьи

Полезные сведения

Тип статьи

Полезные сведения

Компетенции

Администратор Linux, MongoDB

Статус

ЧЕРНОВИК

Сложность

Легко

 Введение

Зачастую во время траблшутинга на стенде заказчика необходимо посмотреть и проверить базу данных MongoDB. Первым делом нам нужно получить логин и пароль от MongoDB:

ID=$(docker ps | grep visiology.admin | awk '{print $1}') && echo `docker exec -it $ID sh -c "cat secrets/MONGO_AUTH_USER"` && echo `docker exec -it $ID sh -c "cat secrets/MONGO_AUTH_PASSWORD"` # Первой строчкой возвращается логин, второй - пароль

Затем заходим в контейнер visiology_mongodb и логинимся в консоль mongo:

$ mongo -u <логин> -p <пароль> VisiologyVA or $ mongosh "mongodb://127.0.0.1:27017" --username zidan --authenticationDatabase admin

Любое изменение в Монге напрямую может привести к поломке платформы. Польза от статьи в основном от операций поиска, просмотра, логирования. Любые модификации применяются только в конкретных кейсах поддержки, где это реально необходимо.


1. Просмотр сущностей.

Показать список баз данных:

>show dbs >show databases

Выбрать/использовать базу данных:

Если базы с таким именем не существует, она автоматически создастся

Показать коллекции в БД:


2. Ввод данных

Создать коллекцию в БД:

Ввод содержимого в БД:

insertOne используется при создании одного объекта. Если при создании объекта указываются ранее несуществующие коллекции, они создаются автоматически.


3. Поиск сущностей

Вывод содержимого коллекции:

Поиск по объектам:

Поиск с сортировкой:

Вывод указанных полей массива:

Здесь мы вернули названия дашборда и названия листов, где используется виджет Гистограмма (ColumnChart). Вывод:


4. Изменение данных

Для того, чтобы внести правки в один объект, используется оператор updateOne:

Например:

В этом случае мы добавили новое свойство объекта - description. Если такое свойство уже существует, то содержимое свойства изменится на заданное.

Для того, чтобы полностью заменить один объект другим, используется оператор replaceOne:

Теперь этот объект имеет следующий вид:


5. Удаление данных/сущностей

Удаление данных из коллекции:

Также, например, можно удалить пользователей в зависимости от времени их создания (импорта).

Для удаления отдельного свойства объекта используется оператор $unset. С его помощью можно удалять сразу несколько полей:

Удаление коллекции:


6. Повышение прав и диагностика БД/коллекций

По умолчанию у пользователя нет доступа к средствам диагностики баз данных. От лица обычного пользователя с правами readWrite (подробнее о ролях/правах в mongoDB здесь) мы сможем разве что проверить коллекцию на целостность:

После чего возвращается общая информация о коллекции, где также будет значение valid: false/true, если данные повреждены/не повреждены.

Если же мы хотим получать больше информации, то нам необходимо внести изменения в файл /init-db.js, который находится в корневой папке docker-образа visiology_mongodb. Именно этот файл отвечает за создание пользователей в mongoDB. Копируем его из контейнера:

Находим в скрипте команды для создания пользователя:

Добавляем в базу данных admin своего пользователя с расширенными правами:

Далее нужно выполнить маппинг изменённого init-db.js в каталог Docker хоста. Для этого мы открываем файл platform.yml (лежит в папке с дистрибутивом платформы) для редактирования. В этом файле ищем секцию "mongodb:" и в блоке "volumes:" добавляем следующее:

Теперь, если у нас будет выполняться перезапуск платформы, файл init-db.js будет взят из каталога /home/<username>/distrib_2.26/, который мы прописали в yml файле. После этого можно перезапускать платформу, заходить в контейнер visiology_mongodb и логиниться в консоль монго:

С этого момента нам доступен весь набор команд для диагностики. Например, мы можем посмотреть общую информацию об используемом билде mongoDB:

Также мы можем посмотреть обзор состояния базы данных:

Эта команда выводит огромное количество данных. Поэтому можно обозначить поле или объект в команде:


7. Логирование

В консоли mongo мы увидим только часть информации. Иногда для траблшутинга также бывает полезен просмотр истории событий на стенде. Здесь мы можем отследить историю изменения пользователей, дашбордов и остальных объектов. Тогда приходится прибегать к просмотрам логов. По умолчанию логи mongo доступны в stdout. Увидеть их мы можем следующим образом:

Если необходимо, логи можно выводить в отдельный файл. Для этого нужно внести следующие изменения в platform.yml:

где -v - уровень детализации логов, необходимый для получения данных о редактировании объектов от 0 (отсутствие индекса -v) до 5 (-vvvvv);

--logpath /data/db/mongo.log - здесь указываем файл, в который пишутся логи. В таком случае, при каждом перезапуске контейнера будет создаваться новый файл mongo.log, а предыдущий будет перезаписан с названием mongo.log.<timestamp>.

Другой доступный метод логирования - вывод логов в grafana. Для его настройки нужно будет скопировать файл /etc/promtail/docker-config.yaml из docker-контейнера visiology_promtail и добавить компонент mongodb в поле selector:

Затем маппим отредактированный yaml файл обратно в контейнер promtail: вносим в grafana.yml соответстующие изменения:

Не забываем про опции логирования в файле platform.yml:

После перезапуска платформы мы сможем отследить события в mongo на портале администрирования. Например, создание нового пользователя через портал выполняется платформой через команду insert, то есть отследить это событие мы можем так:

Аналогично, findAndModify - для изменения или удаления пользователя.

Для событий с дашбордами и виджетами подойдёт следующий фильтр:

Также через логи мы можем извлечь информацию об истории изменения объектов. Для этого в запросе достаточно указать имя объекта.

В результате мы видим все timestamp'ы, когда менялся объект, и можем отследить изменения в нём.

2022-07-29 12:53:14

{"log":"{\"t\":{\"$date\":\"2022-07-29T09:53:14.732+00:00\"},\"s\":\"I\", \"c\":\"COMMAND\", \"id\":51803, \"ctx\":\"conn7\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"command\",\"ns\":\"VisiologyVA.Users\",\"command\":{\"findAndModify\":\"Users\",\"query\":{\"UserName\":\"Testuser\"},\"new\":false,\"remove\":false,\"upsert\":false,\"fields\":{},\"update\":{\"$set\":{\"Created\":{\"$date\":\"2022-07-29T09:52:28.791Z\"},\"LastLogin\":null,\"IsBlocked\":false,\"AccessFailedCount\":0,\"LockoutEndDate\":null,\"Roles\":[\"Все авторизованные пользователи\",\"Оператор ввода\"],\"Email\":\"\",\"MiddleName\":\"\",\"FamilyName\":\"Тест\",\"GivenName\":\"\",\"UserName\":\"Testuser\"}},\"lsid\":{\"id\":{\"$uuid\":\"9c33608a-2e7e-4e94-a67d-ff3a3debb260\"}},\"$db\":\"VisiologyVA\"},\"planSummary\":\"IXSCAN { UserName: 1 }\",\"keysExamined\":1,\"docsExamined\":1,\"nMatched\":1,\"nModified\":1,\"numYields\":0,\"queryHash\":\"F3F3F41C\",\"planCacheKey\":\"A72AB840\",\"reslen\":726,\"locks\":{\"ParallelBatchWriterMode\":{\"acquireCount\":{\"r\":1}},\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"w\":1}},\"Database\":{\"acquireCount\":{\"w\":1}},\"Collection\":{\"acquireCount\":{\"w\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"flowControl\":{\"acquireCount\":1,\"timeAcquiringMicros\":2},\"storage\":{},\"protocol\":\"op_msg\",\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T09:53:14.732690954Z"}

2022-07-29 12:53:00

{"log":"{\"t\":{\"$date\":\"2022-07-29T09:53:00.772+00:00\"},\"s\":\"I\", \"c\":\"COMMAND\", \"id\":51803, \"ctx\":\"conn7\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"command\",\"ns\":\"VisiologyVA.Users\",\"command\":{\"find\":\"Users\",\"filter\":{\"UserName\":\"Testuser\"},\"projection\":{},\"limit\":1,\"singleBatch\":true,\"batchSize\":1,\"lsid\":{\"id\":{\"$uuid\":\"9c33608a-2e7e-4e94-a67d-ff3a3debb260\"}},\"$db\":\"VisiologyVA\"},\"planSummary\":\"IXSCAN { UserName: 1 }\",\"keysExamined\":1,\"docsExamined\":1,\"cursorExhausted\":true,\"numYields\":0,\"nreturned\":1,\"queryHash\":\"F3F3F41C\",\"planCacheKey\":\"A72AB840\",\"reslen\":743,\"locks\":{\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"r\":1}},\"Database\":{\"acquireCount\":{\"r\":1}},\"Collection\":{\"acquireCount\":{\"r\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"storage\":{},\"protocol\":\"op_msg\",\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T09:53:00.772390105Z"}

2022-07-29 12:52:56

{"log":"{\"t\":{\"$date\":\"2022-07-29T09:52:56.268+00:00\"},\"s\":\"I\", \"c\":\"COMMAND\", \"id\":51803, \"ctx\":\"conn10\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"command\",\"ns\":\"VisiologyVA.Users\",\"command\":{\"findAndModify\":\"Users\",\"query\":{\"UserName\":\"Testuser\"},\"new\":false,\"remove\":false,\"upsert\":false,\"fields\":{},\"update\":{\"$set\":{\"Created\":{\"$date\":\"2022-07-29T09:52:28.791Z\"},\"LastLogin\":null,\"IsBlocked\":false,\"AccessFailedCount\":0,\"LockoutEndDate\":null,\"Roles\":[\"Все авторизованные пользователи\",\"Менеджер Севастополя\",\"Оператор ввода\"],\"Email\":\"\",\"MiddleName\":\"\",\"FamilyName\":\"Тест\",\"GivenName\":\"\",\"UserName\":\"Testuser\"}},\"lsid\":{\"id\":{\"$uuid\":\"0e5ebfd4-ed22-4882-91f0-155d2681ce19\"}},\"$db\":\"VisiologyVA\"},\"planSummary\":\"IXSCAN { UserName: 1 }\",\"keysExamined\":1,\"docsExamined\":1,\"nMatched\":1,\"nModified\":1,\"numYields\":0,\"queryHash\":\"F3F3F41C\",\"planCacheKey\":\"A72AB840\",\"reslen\":644,\"locks\":{\"ParallelBatchWriterMode\":{\"acquireCount\":{\"r\":1}},\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"w\":1}},\"Database\":{\"acquireCount\":{\"w\":1}},\"Collection\":{\"acquireCount\":{\"w\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"flowControl\":{\"acquireCount\":1,\"timeAcquiringMicros\":1},\"storage\":{},\"protocol\":\"op_msg\",\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T09:52:56.268591674Z"}

2022-07-29 12:52:43

{"log":"{\"t\":{\"$date\":\"2022-07-29T09:52:43.357+00:00\"},\"s\":\"I\", \"c\":\"COMMAND\", \"id\":51803, \"ctx\":\"conn6\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"command\",\"ns\":\"VisiologyVA.Users\",\"command\":{\"find\":\"Users\",\"filter\":{\"UserName\":\"Testuser\"},\"projection\":{},\"limit\":1,\"singleBatch\":true,\"batchSize\":1,\"lsid\":{\"id\":{\"$uuid\":\"0e5ebfd4-ed22-4882-91f0-155d2681ce19\"}},\"$db\":\"VisiologyVA\"},\"planSummary\":\"IXSCAN { UserName: 1 }\",\"keysExamined\":1,\"docsExamined\":1,\"cursorExhausted\":true,\"numYields\":0,\"nreturned\":1,\"queryHash\":\"F3F3F41C\",\"planCacheKey\":\"A72AB840\",\"reslen\":661,\"locks\":{\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"r\":1}},\"Database\":{\"acquireCount\":{\"r\":1}},\"Collection\":{\"acquireCount\":{\"r\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"storage\":{},\"protocol\":\"op_msg\",\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T09:52:43.357954427Z"}

2022-07-29 12:52:28

{"log":"{\"t\":{\"$date\":\"2022-07-29T09:52:28.815+00:00\"},\"s\":\"I\", \"c\":\"COMMAND\", \"id\":51803, \"ctx\":\"conn6\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"command\",\"ns\":\"VisiologyVA.Users\",\"command\":{\"insert\":\"Users\",\"documents\":[{\"IsBuiltIn\":false,\"Roles\":[\"Все авторизованные пользователи\"],\"IsBlocked\":false,\"_id\":{\"$oid\":\"62e3addc01b621dcea253ad3\"},\"UserName\":\"Testuser\",\"Password\":\"\",\"GivenName\":\"\",\"FamilyName\":\"Тест\",\"MiddleName\":\"\",\"Email\":\"\",\"Created\":{\"$date\":\"2022-07-29T09:52:28.791Z\"},\"LastLogin\":null,\"LockoutEndDate\":null,\"AccessFailedCount\":0,\"IsActive\":\"fYurz3QZPcnp5SrY80se+kKLzZ3U+m4LW9/SED7bH5Q5cHmWaUfD2Zd1Dr1h00ATXbT7qzTr/oGNFTK0AsU3ckrNhwpaqxBd5U04/ZyPoDf7G0ylo1Sl2IBdfQBoHLlVLbfsQeyOKeY6PRFphEHvXnehbQKUyhnHyAdSUAAewoS9Xdx53ZuDLou6W+BF3z9miLYbD17PPRPRTPn7io7Sz2Ltj8yKCdJst3yRPkzNQ1w=\"}],\"ordered\":true,\"lsid\":{\"id\":{\"$uuid\":\"9c33608a-2e7e-4e94-a67d-ff3a3debb260\"}},\"$db\":\"VisiologyVA\"},\"ninserted\":1,\"keysInserted\":2,\"numYields\":0,\"reslen\":45,\"locks\":{\"ParallelBatchWriterMode\":{\"acquireCount\":{\"r\":1}},\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"w\":1}},\"Database\":{\"acquireCount\":{\"w\":1}},\"Collection\":{\"acquireCount\":{\"w\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"flowControl\":{\"acquireCount\":1,\"timeAcquiringMicros\":1},\"storage\":{},\"protocol\":\"op_msg\",\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T09:52:28.816208561Z"}

Таким же образом мы можем отследить изменение лицензионных ключей:

2022-07-29 15:44:04

{"log":"{\"t\":{\"$date\":\"2022-07-29T12:44:04.440+00:00\"},\"s\":\"I\", \"c\":\"COMMAND\", \"id\":51803, \"ctx\":\"conn7\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"command\",\"ns\":\"VisiologyVA.GeneralSettings\",\"command\":{\"findAndModify\":\"GeneralSettings\",\"query\":{},\"new\":false,\"remove\":false,\"upsert\":false,\"fields\":{},\"update\":{\"$set\":{\"License\":\"IZOspVrpR9kzk+QEmtXJDE3fW2VOLX64EkfuiYmZA3CpsGcAFLpqduDewo1I5s4GInGVqMKTymeJz2y+js2RMHqpdAED5XFNw+F3+QAbK8ySBFju15QCleYLo/60bSwTV50BSoheb0uDimmd8s32Q38SBCMfdMZSevpKETKpW6n82WKTF/9uyTuTzlPHT4rcRWCGteaboGm2c6ixs4NEftToPlZ2XPddfyEYcsvcTd+5N/5cpJkgYpA2E7yC2VQn0HkbhUR+hMfXlfDgAqGH3NgWe/JYGCAicL+WXyb/QzQhaJb7NSwBsBwEX8P8ZGom5F1T9dYBiCA4n/Io3pXtRw==5bhYBfgZv/Q0EEti53WSn3lElxhgAmzAX6bXYE4yIEw+xKImQG2mNDqWjSu3iw6AGiGBTDHCjWYxkIBhW3n+W+PKNAIm8fvYqXbhVmeZGclhMxYDGgkTyRmajr/ryIy8141UuRLuz9QtvK0aIWp3lsWyMA+eY2gx/IhLQOvsJu7b2R0Iky9YXqbyQBVljPlI7rSBlOTCjazzYdeK52kAULpvS/ENNx6EdUSwY+nfN1jma7APD5ZlR831DNHXzflVB6/Wt91iv4D4RYmQnSL2DA==\"}},\"lsid\":{\"id\":{\"$uuid\":\"70b63661-d47a-4861-877e-6ea8404bc0b2\"}},\"$db\":\"VisiologyVA\"},\"planSummary\":\"COLLSCAN\",\"keysExamined\":0,\"docsExamined\":1,\"nMatched\":1,\"nModified\":1,\"numYields\":0,\"reslen\":2241,\"locks\":{\"ParallelBatchWriterMode\":{\"acquireCount\":{\"r\":1}},\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"w\":1}},\"Database\":{\"acquireCount\":{\"w\":1}},\"Collection\":{\"acquireCount\":{\"w\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"flowControl\":{\"acquireCount\":1},\"storage\":{},\"protocol\":\"op_msg\",\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T12:44:04.440879728Z"}

2022-07-29 15:43:13

{"log":"{\"t\":{\"$date\":\"2022-07-29T12:43:13.879+00:00\"},\"s\":\"I\", \"c\":\"COMMAND\", \"id\":51803, \"ctx\":\"conn6\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"command\",\"ns\":\"VisiologyVA.GeneralSettings\",\"command\":{\"findAndModify\":\"GeneralSettings\",\"query\":{},\"new\":false,\"remove\":false,\"upsert\":false,\"fields\":{},\"update\":{\"$set\":{\"License\":\"blahblah\"}},\"lsid\":{\"id\":{\"$uuid\":\"70b63661-d47a-4861-877e-6ea8404bc0b2\"}},\"$db\":\"VisiologyVA\"},\"planSummary\":\"COLLSCAN\",\"keysExamined\":0,\"docsExamined\":1,\"nMatched\":1,\"nModified\":0,\"numYields\":0,\"reslen\":2241,\"locks\":{\"ParallelBatchWriterMode\":{\"acquireCount\":{\"r\":1}},\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"w\":1}},\"Database\":{\"acquireCount\":{\"w\":1}},\"Collection\":{\"acquireCount\":{\"w\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"flowControl\":{\"acquireCount\":1,\"timeAcquiringMicros\":1},\"storage\":{},\"protocol\":\"op_msg\",\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T12:43:13.879824929Z"}

2022-07-29 15:31:46

{"log":"{\"t\":{\"$date\":\"2022-07-29T12:31:46.841+00:00\"},\"s\":\"I\", \"c\":\"WRITE\", \"id\":51803, \"ctx\":\"conn63\",\"msg\":\"Slow query\",\"attr\":{\"type\":\"update\",\"ns\":\"VisiologyVA.GeneralSettings\",\"appName\":\"MongoDB Shell\",\"command\":{\"q\":{\"_id\":{\"$oid\":\"59cdff503933cf1405125a14\"}},\"u\":{\"$set\":{\"License\":\"blahblah\"}},\"multi\":false,\"upsert\":false},\"planSummary\":\"IDHACK\",\"keysExamined\":1,\"docsExamined\":1,\"nMatched\":1,\"nModified\":1,\"numYields\":0,\"locks\":{\"ParallelBatchWriterMode\":{\"acquireCount\":{\"r\":1}},\"ReplicationStateTransition\":{\"acquireCount\":{\"w\":1}},\"Global\":{\"acquireCount\":{\"w\":1}},\"Database\":{\"acquireCount\":{\"w\":1}},\"Collection\":{\"acquireCount\":{\"w\":1}},\"Mutex\":{\"acquireCount\":{\"r\":1}}},\"flowControl\":{\"acquireCount\":1,\"timeAcquiringMicros\":1},\"storage\":{},\"durationMillis\":0}}\n","stream":"stdout","attrs":{"component":"mongodb"},"time":"2022-07-29T12:31:46.841469259Z"}


8. Бэкап и восстановление базы данных

За создание резервных копий серверов, баз данных или коллекций отвечает утилита mongodump. Если запустить mongodump без каких-либо опций, файл dump создастся на локальном хосте в директории /dump.

Также вы можете указать хост и порт сервера, к которому утилите mongodump нужно присоединиться:

Для указания директории можно использовать индекс -o или - -out:

Чтобы ограничить резервную копию одной коллекцией, можно указать - -db и  - -collection, как опции:

Например, при создании бэкапа баз данных Visiology применяется следующая команда:

Резервную копию восстанавливает утилита mongorestore.

По аналогии, в Visiology восстановление данных осуществляется по следующему скрипту: