Рубрики
Без рубрики

Интеграция MongoDB с Python с помощью PyMongo

MongoDB-это нереляционная база данных на основе документов, которая обеспечивает большую и легкую горизонтальную масштабируемость. В этой статье мы будем использовать PyMongo для подключения к базе данных MongoDB и выполнения CRUD-операций с помощью Python.

Автор оригинала: Robley Gori.

Интеграция MongoDB с Python с помощью PyMongo

Вступление

В этом посте мы погрузимся в MongoDB как хранилище данных с точки зрения Python. С этой целью мы напишем простой сценарий, чтобы продемонстрировать, чего мы можем достичь и какие выгоды мы можем извлечь из этого.

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

Базы данных позволяют нам организовывать и хранить эти данные, а также контролировать, как мы храним, получаем доступ и защищаем информацию.

Базы данных NoSQL

Существует два основных типа баз данных – реляционные и нереляционные .

Реляционные базы данных позволяют нам хранить, получать доступ и манипулировать данными по отношению к другой части данных в базе данных. Данные хранятся в организованных таблицах со строками и столбцами с отношениями, связывающими информацию между таблицами. Для работы с этими базами данных мы используем Structured Query Language (SQL), а примеры включают MySQL и PostgreSQL .

Нереляционные базы данных хранят данные ни в реляционных, ни в табличных базах данных, как в реляционных базах данных. Они также называются базами данных NoSQL , поскольку мы не используем SQL для взаимодействия с ними.

Кроме того, базы данных NoSQL можно разделить на Key-Value stores , Graph stores , Column stores и Document Stores , под которые подпадает MongoDB.

MongoDB и когда его использовать

MongoDB-это хранилище документов и нереляционная база данных . Это позволяет нам хранить данные в коллекциях , которые состоят из документов .

В MongoDB документ представляет собой просто JSON-подобный двоичный формат сериализации , называемый a BONUS или Binary-JSON, и имеет максимальный размер 16 мегабайт. Это ограничение размера используется для обеспечения эффективного использования памяти и полосы пропускания во время передачи.

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

Документы состоят из пар “поле-значение”, как и в обычных данных JSON. Однако этот формат BSON также может содержать больше типов данных, таких как Date types и Binary Data types. BENSON был разработан, чтобы быть легким, легко проходимым и эффективным при кодировании и декодировании данных в BSON и из BSON.

Будучи хранилищем данных NoSQL, MongoDB позволяет нам пользоваться преимуществами, которые дает использование нереляционной базы данных по сравнению с реляционной. Одним из преимуществ является то, что он обеспечивает высокую масштабируемость за счет эффективного горизонтального масштабирования путем сегментирования или секционирования данных и размещения их на нескольких машинах.

MongoDB также позволяет хранить большие объемы структурированных, полуструктурированных и неструктурированных данных без необходимости поддерживать отношения между ними. Будучи открытым исходным кодом, стоимость внедрения MongoDB держится на низком уровне только за счет технического обслуживания и экспертных знаний.

Как и любое другое решение, использование MongoDB имеет свои недостатки. Первый из них заключается в том, что он не поддерживает отношений между хранящимися данными. Из-за этого трудно выполнять ACID-транзакции , которые обеспечивают согласованность.

Сложность увеличивается при попытке поддержать транзакции ACID. MongoDB, как и другие хранилища данных NoSQL, не так совершенен, как реляционные базы данных, и это может затруднить поиск экспертов.

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

С гибкими/нереляционными данными нам не нужно поддерживать свойства ACID при хранении данных, в отличие от реляционных баз данных. MongoDB также позволяет нам легко масштабировать данные в новые узлы.

Однако при всех своих преимуществах MongoDB не идеален, когда наши данные реляционны по своей природе. Например, если мы храним записи клиентов и их заказы.

В этой ситуации нам понадобится реляционная база данных для поддержания отношений между нашими данными, которые важны. Он также не подходит для использования MongoDB, если нам нужно соблюдать свойства КИСЛОТЫ.

Взаимодействие с MongoDB через оболочку Mongo

Для работы с MongoDB нам нужно будет установить сервер MongoDB , который мы можем скачать с официальной домашней страницы . Для этой демонстрации мы будем использовать бесплатный сервер сообщества.

Сервер MongoDB поставляется с оболочкой Mongo Shell , которую мы можем использовать для взаимодействия с сервером через терминал.

Чтобы активировать оболочку, просто введите mongo в вашем терминале. Вас встретит информация о настройке сервера MongoDB, включая версию оболочки MongoDB и Mongo, а также URL-адрес сервера.

Например, наш сервер работает на:

mongodb://127.0.0.1:27017

В MongoDB база данных используется для хранения коллекций, содержащих документы. Через оболочку Mongo мы можем создать новую базу данных или переключиться на существующую с помощью команды use :

> use SeriesDB

Каждая операция, которую мы выполняем после этого, будет выполняться в нашей базе данных Series DB . В базе данных мы будем хранить коллекции, которые аналогичны таблицам в реляционных базах данных.

Например, для целей этого урока давайте добавим несколько серий в базу данных:

> db.series.insertMany([
... { name: "Game of Thrones", year: 2012},
... { name: "House of Cards", year: 2013 },
... { name: "Suits", year: 2011}
... ])

Нас встречают с:

{
    "acknowledged" : true,
    "insertedIds" : [
        ObjectId("5e300724c013a3b1a742c3b9"),
        ObjectId("5e300724c013a3b1a742c3ba"),
        ObjectId("5e300724c013a3b1a742c3bb")
    ]
}

Чтобы извлечь все документы, хранящиеся в нашей коллекции series , мы используем db.inventory.find ({}) , SQL-эквивалент которого равен SELECT * FROM series . Передача пустого запроса (т. е. {} ) вернет все документы:

> db.series.find({})

{ "_id" : ObjectId("5e3006258c33209a674d1d1e"), "name" : "The Blacklist", "year" : 2013 }
{ "_id" : ObjectId("5e300724c013a3b1a742c3b9"), "name" : "Game of Thrones", "year" : 2012 }
{ "_id" : ObjectId("5e300724c013a3b1a742c3ba"), "name" : "House of Cards", "year" : 2013 }
{ "_id" : ObjectId("5e300724c013a3b1a742c3bb"), "name" : "Suits", "year" : 2011 }

Мы также можем запросить данные, используя условие равенства, например, чтобы вернуть все телесериалы, премьера которых состоялась в 2013 году:

> db.series.find({ year: 2013 })
{ "_id" : ObjectId("5e3006258c33209a674d1d1e"), "name" : "The Blacklist", "year" : 2013 }
{ "_id" : ObjectId("5e300724c013a3b1a742c3ba"), "name" : "House of Cards", "year" : 2013 }

Эквивалентом SQL будет SELECT * FROM series WHERE .

MongoDB также позволяет нам обновлять отдельные документы с помощью db.collection.Update One () или выполните пакетное обновление с помощью db.collection.UpdateMany() . Например, чтобы обновить год выпуска для Suits :

> db.series.updateOne(
{ name: "Suits" },
{
    $set: { year: 2010 }
}
)
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

Наконец, для удаления документов оболочка Mongo предлагает db.collection.deleteOne() и db.collection.удалить многие функции () .

Например, удалить все серии, премьера которых состоялась в 2012 , мы бы побежали:

> db.series.deleteMany({ year: 2012 })
{ "acknowledged" : true, "deletedCount" : 2 }

Более подробную информацию об операциях CRUD на MongoDB можно найти в онлайн-справочнике включая дополнительные примеры, выполнение операций с условиями, атомарность и сопоставление концепций SQL с концепциями и терминологией MongoDB.

Интеграция Python с MongoDB

MongoDB предоставляет драйверы и инструменты для взаимодействия с хранилищем данных MongoDB с использованием различных языков программирования, включая Python, JavaScript, Java, Go и C#.

PyMongo – это официальный драйвер MongoDB для Python, и мы будем использовать его для создания простого скрипта, который будет использоваться для манипулирования данными, хранящимися в нашей базе данных SeriesDB .

С помощью Python 3.6+ и Virtualenv , установленных на наших машинах, давайте создадим виртуальную среду для нашего приложения и установим PyMongo через pip:

$ virtualenv --python=python3 env --no-site-packages
$ source env/bin/activate
$ pip install pymongo

Использование PyMongo , мы собираемся написать простой скрипт, который мы можем выполнить для выполнения различных операций с нашей базой данных MongoDB.

Подключение к MongoDB

Во-первых, мы импортируем pymongo в наш mongo_db_script.py и создайте клиент, подключенный к локально запущенному экземпляру MongoDB:

import pymongo

# Create the client
client = MongoClient('localhost', 27017)

# Connect to our database
db = client['SeriesDB']

# Fetch our series collection
series_collection = db['series']

До сих пор мы создали клиент, который подключается к вашему серверу MongoDB и использует его для получения нашей базы данных “Series DB”. Затем мы извлекаем нашу коллекцию “серий” и храним ее в объекте.

Создание документов

Чтобы сделать наш скрипт более удобным, мы напишем функции, которые оборачиваются вокруг PyMongo , чтобы мы могли легко манипулировать данными. Мы будем использовать Python словари для представления документов и передадим эти словари нашим функциям. Во-первых, давайте создадим функцию для вставки данных в нашу коллекцию “серий”:

# Imports truncated for brevity

def insert_document(collection, data):
    """ Function to insert a document into a collection and
    return the document's id.
    """
    return collection.insert_one(data).inserted_id

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

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

Теперь давайте попробуем добавить шоу с помощью нашей функции:

new_show = {
    "name": "FRIENDS",
    "year": 1994
}
print(insert_document(series_collection, new_show))

Выход таков:

5e4465cfdcbbdc68a6df233f

Когда мы запускаем наш скрипт, _id нашего нового шоу печатается на терминале, и мы можем использовать этот идентификатор для получения шоу позже.

Мы можем предоставить значение _id вместо того, чтобы назначать его автоматически, что мы бы предоставили в словаре:

new_show = {
    "_id": "1",
    "name": "FRIENDS",
    "year": 1994
}

И если бы мы попытались сохранить документ с существующим _id , нас встретила бы ошибка, похожая на следующую:

DuplicateKeyError: E11000 duplicate key error index: SeriesDB.series.$id dup key: { : 1}

Извлечение Документов

Для извлечения документов из базы данных мы будем использовать find_document() , который запрашивает нашу коллекцию для одного или нескольких документов. Наша функция получит словарь, содержащий элементы, по которым мы хотим отфильтровать, и необязательный аргумент, указывающий, хотим ли мы получить один документ или несколько документов:

# Imports and previous code truncated for brevity

def find_document(collection, elements, multiple=False):
    """ Function to retrieve single or multiple documents from a provided
    Collection using a dictionary containing a document's elements.
    """
    if multiple:
        results = collection.find(elements)
        return [r for r in results]
    else:
        return collection.find_one(elements)

А теперь давайте воспользуемся этой функцией, чтобы найти некоторые документы:

result = find_document(series_collection, {'name': 'FRIENDS'})
print(result)

При выполнении нашей функции мы не предоставили параметр multiple , и в результате получился один документ:

{'_id': ObjectId('5e3031440597a8b07d2f4111'), 'name': 'FRIENDS', 'year': 1994}

Когда задан параметр multiple , результатом будет список всех документов в нашей коллекции, для которых атрибут name имеет значение FRIENDS .

Обновление документов

Наша следующая функция, update_document() , будет использоваться для обновления одного конкретного документа. Мы будем использовать _id документа и коллекции, к которой он принадлежит, при его обнаружении:

# Imports and previous code truncated for brevity

def update_document(collection, query_elements, new_values):
    """ Function to update a single document in a collection.
    """
    collection.update_one(query_elements, {'$set': new_values})

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

new_show = {
    "name": "FRIENDS",
    "year": 1995
}
id_ = insert_document(series_collection, new_show)

Сделав это, давайте обновим документ, который мы укажем с помощью _id , возвращенного при его добавлении:

update_document(series_collection, {'_id': id_}, {'name': 'F.R.I.E.N.D.S'})

И, наконец, давайте выберем его, чтобы убедиться, что новое значение было введено на место, и напечатаем результат:

result = find_document(series_collection, {'_id': id_})
print(result)

Когда мы выполняем наш скрипт, мы видим, что наш документ был обновлен:

{'_id': ObjectId('5e30378e96729abc101e3997'), 'name': 'F.R.I.E.N.D.S', 'year': 1995}

Удаление документов

И наконец, давайте напишем функцию для удаления документов:

# Imports and previous code truncated for brevity

def delete_document(collection, query):
    """ Function to delete a single document from a collection.
    """
    collection.delete_one(query)

Поскольку мы используем метод delete_one , за один вызов можно удалить только один документ, даже если запрос совпадает с несколькими документами.

Теперь давайте используем эту функцию для удаления записи:

delete_document(series_collection, {'_id': id_})

Если мы попытаемся получить тот же самый документ:

result = find_document(series_collection, {'_id': id_})
print(result)

Нас встречают с ожидаемым результатом:

None

Следующие Шаги

Мы выделили и использовали несколько методов PyMongo для взаимодействия с нашим сервером MongoDB из скрипта Python. Однако мы не использовали все методы, доступные нам через модуль.

Все доступные методы можно найти в официальной документации PyMongo и классифицируются в соответствии с подмодулями.

Мы написали простой скрипт, который выполняет элементарную функциональность CRUD в базе данных MongoDB. Хотя мы могли бы импортировать функции в более сложную кодовую базу или, например, в приложение Flask/Django, эти фреймворки уже имеют библиотеки для достижения тех же результатов. Эти библиотеки делают его проще, удобнее и помогают нам более надежно подключаться к MongoDB.

Например, с Django мы можем использовать такие библиотеки , как Django MongoDB Engine и Djongo , в то время как Flask имеет Flask-PyMongo , который помогает преодолеть разрыв между Flask и PyMongo для облегчения бесшовного подключения к базе данных MongoDB.

Вывод

MongoDB-это хранилище документов, которое относится к категории нереляционных баз данных (NoSQL). Он имеет определенные преимущества по сравнению с реляционными базами данных, а также некоторые недостатки.

Хотя он не подходит для всех ситуаций, мы все еще можем использовать MongoDB для хранения данных и манипулирования данными из наших приложений Python с помощью PyMongo среди других библиотек – позволяет нам использовать мощь MongoDB в ситуациях, когда он лучше всего подходит.

Поэтому мы должны тщательно изучить ваши требования, прежде чем принимать решение об использовании MongoDB для хранения данных.

Сценарий, который мы написали в этом посте, можно найти на GitHub .