NoSQL база данных MongoDB: работа на Python (pymongo)

NoSQL база данных MongoDB: работа на Python (pymongo)

Сегодня познакомимся с интересным инструментом - NoSQL базой данных. Ранее мы мучали MySQL и подобные базы, которые требуют много внимания к SQL-запросам и структуре таблицы. Теперь мы познакомимся с идеальной базой данных для не структурированной информации. То есть мы избавимся от строгого синтаксиса и сможем легко дополнять записи новой информацией. В этом огромный плюс NoSQL-базы для написания различных ботов, которые в дальнейшем будут масштабироваться.

Подготовка

Сначала установим саму MongoBD: переходим на официальный сайт Mongo по ссылке и скачиваем сервер версии 6.0.3 под вашу операционную систему.

Для корректной установки следуйте примерам на скриншотах:

Важно тут выбрать пункт “Complete”. Этот пункт поставит все стандартные настройки и модули, что для начала нам подойдет. Потом, если будете изучать эту БД, сможете настраивать под себя:

В этом пункте важно поставить галочку на “Install MongoDB Compass” - на компьютер установится графический интерфейс для взаимодействия с СУБД.

После установки нам открывается программа MongoDB Compass, где уже вставлены данные для подключения к установленному серверу. Нажимаем кнопку "connect", и мы в нем:

Ниже пример как можно создать базу данных и коллекцию. Коллекции – это аналог таблиц в SQL-базах. В них мы храним информацию, которая нам нужна.

Установка MongoClient и код на Python

Для Windows:

pip install pymongo faker

Для MacOS:

python pip install pymongo faker

Для знакомства с СУБД MongoDB нам хватит сделать несколько методов, таких как: добавление пользователя, получить всю коллекцию, изменить какое-то значение, поиск, по заданным критериям и на этом все. Если вам будет интересна эта СУБД,  вы сможете самостоятельно ознакомиться с другими её возможностями. 

Анонсы всех видео, статей и полезностей - в нашем Telegram🔥
Присоединяйтесь, обсуждайте и автоматизируйте!

У нас будет два файла - pymongoAPI.py и main.py (призываю вас всегда разделять проект на логические модули – это правильный тон в мире программистов Python). Первый файл будет отвечать за взаимодействие с БД, а во втором мы будем пытаться добавлять новые значения и что-то менять. 

Импорты:

from pymongo import MongoClient

Для всего взаимодействия с MongoDB потребуется только сам клиент, который и импортируем.

Класс взаимодействия с MongoDB:

class MongoDB(object):
    def __init__(self, host: str = 'localhost',
                 port: int = 27017,
                 db_name: str = None,
                 collection: str = None):
        self._client = MongoClient(f'mongodb://{host}:{port}')
        self._collection = self._client[db_name][collection]

    def create_user(self, user: dict):
        try:
            if self._collection.find_one({"username": user.get('username')}) == None:
                self._collection.insert_one(user)
                print(f"Added New user: {user.get('username')}")
            else:
                print(f"User: {user.get('username')} in collection")
        except Exception as ex:
            print("[create_user] Some problem...")
            print(ex)

    def get_all_users(self):
        try:
            data = self._collection.find()
            print("Get all users")
            return data
        except Exception as ex:
            print("[get_all] Some problem...")
            print(ex)

    def find_by_username(self, username: str):
        try:
            data = self._collection.find_one({"username": username})
            print("Get user by username")
            return data
        except Exception as ex:
            print("[find_by_username] Some problem...")
            print(ex)

    def change_user(self, username: str, key: str, value: str):
        try:
            if self._collection.find_one({"username": user.get('username')}) is not None:
                self._collection.update_one({"username": username}, {"$set": {key: value}})
            else:
                print(f'User: {username} not find')
        except Exception as ex:
            print("[change_user] Some problem...")
            print(ex)

Разберёмся что за чем идет.

__init__ — это конструктор, он принимает в себя ip адрес сервера, порт, название базы данных и название коллекции. Он создает подключение к серверу и записывает в отдельную внутреннюю переменную. Дальше отдельно вытягивает в переменную нашу базу данных. Часто спрашивают зачем ставить нижней прочерк перед полем – это нужно, чтобы показать другим разработчикам, который показывает, что его трогать не надо (так принято показывать в Python приватные переменные).

Create_user – «кушает» словарь, это связанно с тем, что мы будем сразу передавать нового пользователя. Можно формировать его и внутри метода, но так проще. Сразу скажу, что все запросы к базам данных следует оборачивать в try… except, потому что в случае ошибки у нас не будет «падать» программа. В реальной жизни если из-за этой ошибки пользователи не смогу воспользоваться функциями, у вас могут быть проблемы. 

Теперь переходим к сути. Обращаемся к методу find_one для проверки, существует ли пользователь в коллекции. Внутрь мы передаем словарь ключ (искомое поле) и значение. Если нам в ответ вернется None, то значит такого значения не существует, ну и если словарь, то значит пользователь существует (сразу отмечу, что username у нас будут индивидуальным значением, то есть не будет повторяться). 

Дальше обращаемся к insert_one и передаем словарь пользователя. Чтобы видеть ошибки, мы делаем выводы в консоль о выполненном действии и в случае ошибки показываем модуль с ошибкой.

Get_all_users – с помощью этого метода будем выводить все записи в коллекции. Обращаемся к объекту коллекции и применяем метод find, без каких-либо значений. В ответ мы получаем массив значений и возвращаем его из метода.

Find_by_username – теперь будем искать по уникальному значению в виде username. Принимаем искомого пользователя и обращаемся к методу коллекции find_one. Он будет выводить первое совпадение и возвращать его словарем, если пользователя не существует, то вернется None.

Change_user – последний метод на сегодня, он будет менять значение. Принимает в себя username, key (изменяемое значение) и value (новое значение). В начале идет проверка на наложение пользователя в коллекции, потом используется update_one

Что же это такое, метод, предоставляемый объектом коллекции для обновления записи? Первым значением идет словарь для поиска по значение, потом второй с служебным оператором $set с вложенным вторым словарем, внутри которого находится ключ и его новое значение (подробнее об служебных операторах по ссылке).

Main.py

Теперь идем проверять наш класс. Будем рассматривать код по строчкам, чтобы можно было посмотреть все по очереди и отслеживать, что меняется в БД. Импортируем наш MongoDB из файла mongoAPI. Так же библиотеку для создания несуществующих пользователей.

from mongoAPI import MongoDB
import faker

Дальше создаем объект dbase на основе нашего класса, передаем в него название БД и коллекции с которой будем работать:

dbase = MongoDB(db_name='article', collection='user')

Так же не стоит забывать про объект для создание «фейковых» пользователей:

faker_obj = faker.Faker()

Создаем наш фейковый профиль и посмотрим вывод в консоль:

user_profile = faker_obj.simple_profile()
user_profile['birthdate'] = user_profile['birthdate'].strftime('%d/%m/%Y')
print(user_profile)

Словарь состоит из логина, имени, пола, адреса, почты и даты рождения:

{'username': 'dparker', 'name': 'Megan Morris', 'sex': 'F', 'address': '15074 Conner Lane\nDavidshire, ME 67230', 'mail': 'leslie72@gmail.com', 'birthdate': '24/04/2017'}

Пробуем добавить его в коллекцию:

dbase.create_user(user_profile)

 Выводы в консоль:

{'username': 'ronald44', 'name': 'Carrie Armstrong', 'sex': 'F', 'address': '0829 Cook Key Apt. 678\nKatherinestad, CA 73382', 'mail': 'tammy73@hotmail.com', 'birthdate': '24/08/1998'}

Added New user: ronald44

Как выглядит все в коллекции:

Тут может возникнуть вопрос, что за значение _id? Это уникальный ID, который автоматически создает MongoDB. Можно провести аналогию с Primary Key в MySQL.

Давайте добавим пару случайных пользователей с помощью библиотеки faker и цикла for. Выглядит все так:

for _ in range(3):
    user_profile = faker_obj.simple_profile()
    user_profile['birthdate'] = user_profile['birthdate'].strftime('%d/%m/%Y') 
    dbase.create_user(user_profile)

Добавили пользователей: xwilliams, kylewilliams и obrowning. Так это выглядит в коллекции:

Чтобы посмотреть полную сводку из коллекции надо будет воспользоваться циклом for. Это связано с тем, что в ответ нам идет объект Cursor:

result = dbase.get_all_users()
for i in result:
    print(i)

 Вывод в консоль:

Get all users

{'_id': ObjectId('63790f4edc6a4ce30ed44398'), 'username': 'ronald44', 'name': 'Carrie Armstrong', 'sex': 'F', 'address': '0829 Cook Key Apt. 678\nKatherinestad, CA 73382', 'mail': 'tammy73@hotmail.com', 'birthdate': '24/08/1998'}

{'_id': ObjectId('637910f07d126aae084a4310'), 'username': 'xwilliams', 'name': 'Erin Simmons', 'sex': 'F', 'address': 'PSC 0729, Box 2069\nAPO AP 14417', 'mail': 'suzanne49@hotmail.com', 'birthdate': '05/04/1918'}

{'_id': ObjectId('637910f07d126aae084a4311'), 'username': 'kylewilliams', 'name': 'Jeffrey Miller', 'sex': 'M', 'address': '977 Santos Turnpike Apt. 039\nNew Cynthia, FM 81301', 'mail': 'christopher50@gmail.com', 'birthdate': '16/06/2016'}

{'_id': ObjectId('637910f07d126aae084a4312'), 'username': 'obrowning', 'name': 'Amy Thompson', 'sex': 'F', 'address': '041 Leah Locks Suite 280\nReedport, MI 56259', 'mail': 'vargassarah@hotmail.com', 'birthdate': '25/08/1915'}

Поиск человека по логину:

print(dbase.find_by_username('username'))

 Вывод в консоль:

Get user by username

{'_id': ObjectId('63790f4edc6a4ce30ed44398'), 'username': 'ronald44', 'name': 'Carrie Armstrong', 'sex': 'F', 'address': '0829 Cook Key Apt. 678\nKatherinestad, CA 73382', 'mail': 'tammy73@hotmail.com', 'birthdate': '24/08/1998'}

Теперь изменим пользователю имя на "тест":

dbase.change_user('ronald44', 'name', 'test')

После запуска мы увидим в коллекции следующее:

Заключение

Сегодня мы тестировали СУБД MongoDB - сделали тестовое добавление коллекции и попробовали вносить в базу изменения.

Как вы видите, Mongo очень удобна и гибка, что позволяет легко масштабировать из маленького проекта в большой. Советую вам изучить её более подробно.

Полезные ссылки

Документации библиотеки pymongo: https://pymongo.readthedocs.io/en/stable/

Подробный курс на ютубе: https://www.youtube.com/playlist?list=PL6plRXMq5RABbVCM0dn23PTKO13WcXnbf

Комментарии