Основы базы данных MongoDB
Мы привыкли работать с реляционными базами данных, преимущественно с использованием языка SQL. Однако существует множество СУБД, не поддерживающих данную парадигму, так называемых NoSQL. Может возникнуть вопрос, а зачем нужны такие СУБД? Давайте представим, что нам необходимо хранить базу разнообразных документов, причем у них могут быть разнообразные поля. В случае реляционной СУБД мы можем на каждый тип документов завести отдельную таблицу. Но что если существуют поля, которые могут отсутствовать у некоторых документов? В парадигме реакционных СУБД мы можем заполнять несуществующие поля значением NULL. Но что если у каждого документа может быть вообще разный состав полей, и это не разные типы документов, а все документы одного вида?
Давайте рассмотрим пример. Пусть нам необходимо хранить описания и рецептуру блюд. В парадигме реляционной СУБД мы будем создавать таблицу с перечнем блюд, и отдельную таблицу с рецептурой (перечень ингредиентов), которая связана с таблицей блюд отношением один ко многим. В таблице рецептуры у нас есть такие поля, как ингредиент, его количество, единица измерения. Эта таблица в свою очередь связана с таблицей ингредиентов отношением много ко многим. Но тут еще нужна таблица для единиц измерений. И вот у нас уже «зоопарк» связанных таблиц.
А теперь подумаем, как вся эта структура будет представлена в памяти компьютера. Если мы программируем в парадигме ООП, то у нас наверняка должна быть коллекция блюд, объект этой коллекции – блюдо, содержит коллекцию «рецептура», элемент которой содержат поле типа объект «ингредиент», количество, единицу измерения. Последнее тоже объект. А теперь представим, что у нас есть некий абстрактный класс «Единица измерения», от которого наследуется конкретная единица измерения. Аналогично и с ингредиентами. Разумеется, все поля классов замаплены на конкретные столбцы соответствующих объекту таблиц. Но что если в каком-нибудь дочернем классе появятся новые поля? Добавлять таблицы для этих классов, раздувать «зоопарк» таблиц еще больше?
Другой вариант архитектуры – это документоориентированная NoSQL СУБД, например, MongoDB. О ней и пойдет речь в этой статье. Я расскажу, как создать базу данных MongoDB и работать с ней средствами языка Python.
Итак, регистрируемся на сайте https://www.mongodb.com. Обратите внимание, из России этот сервис не работает, видимо из-за санкций, так что используйте прокси. Далее на закладке Database создадим новую базу данных:
База данных представлена в виде дерева, «листики» которого – это таблица. Если кликнуть по таблице, то можно увидеть ее содержимое:
Как видим, документы, извлекаемые из базы данных, представляют собой JSON-объекты. Здесь же есть кнопки для создания и удаления объектов базы данных, кроме того, можно ввести фильтр для выборки данных.
Каким образом подключиться к базе данных через Python?
Для начала надо установить и подключить библиотеку pymongo. Это можно сделать через pip, введя вот такую команду в командную строку:
python -m pip install pymongo
Ну и можно пользоваться:
import pymongo
from pymongo.server_api import ServerApi
client = pymongo.MongoClient("Строка подключения", server_api=ServerApi('1'))
db = client.test
try:
print("MongoDB version is %s" % client.server_info()['version'])
except pymongo.errors.OperationFailure as error:
print(error)
quit(1)
my_collection = db.foods
my_collection.delete_many({
"calories": {
"$lt": 300
}
})
Сформировать строку подключения можно в браузере mongoDB, нажав на кнопочку «Connect»:
Откроется вот такое окно, там надо выбрать «Connect your application»:
Выбираем язык Python:
И видим строку подключения:
Копируем ее в программу, вместо <password> ставим ваш реальный пароль.
Чтобы создать новую таблицу, можно воспользоваться методов create_collection базы данных:
import pymongo
from pymongo.server_api import ServerApi
client = pymongo.MongoClient("mongodb+srv://megabax:<Пароль>@cluster0.vwremdq.mongodb.net/?retryWrites=true&w=majority", server_api=ServerApi('1'))
db = client.test
try:
print("MongoDB version is %s" % client.server_info()['version'])
except pymongo.errors.OperationFailure as error:
print(error)
quit(1)
db.create_collection("MyTable")
После выполнения программы в списке таблиц базы данных появится наша таблица:
В общих чертах, как работать с базой данных mongoDB. Как видим из примеров кода, сначала мы создаем подключение (клиента). Через него получаем объект базы данных (это поле объекта клиента, имя которого совпадает с именем базы данных). Сам объект базы данных содержит в себе поля, соответствующие таблицам. Эти таблицы представляют собой коллекцию элементов таблицы. Эти коллекции содержат в себе методы по манипулированию данными, такие как перебор элементов, поиск, добавление и удаление. Давайте, например, создадим тестовую базу данных, путем добавления в цикле множества элементов методом insert_one:
import pymongo
from pymongo.server_api import ServerApi
import random
import string
def generate_random_string(length):
letters = string.ascii_lowercase
rand_string = ''.join(random.choice(letters) for i in range(length))
print("Random string of length", length, "is:", rand_string)
return rand_string
def get_random_features():
dict={}
ln=random.randint(1,10)
for i in range(ln):
dict["feature"+str(i)]=generate_random_string(random.randint(3,15))
return dict
client = pymongo.MongoClient("mongodb+srv://megabax:<Пароль>@cluster0.vwremdq.mongodb.net/?retryWrites=true&w=majority", server_api=ServerApi('1'))
db = client.test
try:
print("MongoDB version is %s" % client.server_info()['version'])
except pymongo.errors.OperationFailure as error:
print(error)
quit(1)
mongo_collection = db.goods
for i in range(100):
mongo_collection.insert_one({
"_id": i,
"name": generate_random_string(random.randint(3,15)),
"price": round(random.random()*100,2),
"features": get_random_features(),
"quantity": random.randint(1,10000)
})
Теперь попробуем перебрать элементы таблицы:
import pymongo
from pymongo.server_api import ServerApi
client = pymongo.MongoClient("mongodb+srv://megabax:<Пароль>@cluster0.vwremdq.mongodb.net/?retryWrites=true&w=majority", server_api=ServerApi('1'))
db = client.test
try:
print("MongoDB version is %s" % client.server_info()['version'])
except pymongo.errors.OperationFailure as error:
print(error)
quit(1)
my_collection = db.goods
my_cursor = my_collection.find()
for item in my_cursor:
print(item["name"])
Этот код переберет все элементы, и выведет значения их полей name. Можно перебрать по фильтру:
my_cursor = my_collection.find({
"name": "jgdpspvonpune"
})
Стоит заметить, что в качестве полей у элементов коллекции может быть и коллекция, и какой-либо другой объект. Например, у элемента коллекции goods есть элемент features, который сам по себе является объектом, а именно словарем:
А сейчас мы сделаем следующее. Очистим коллекцию goods, а потом снова перезаполним ее, но немного по-другому. Для этого можно вызвать метод delete_many(), а в качестве параметров указать пустой фильтр:
import pymongo
from pymongo.server_api import ServerApi
client = pymongo.MongoClient("mongodb+srv://megabax:<Пароль>@cluster0.vwremdq.mongodb.net/?retryWrites=true&w=majority", server_api=ServerApi('1'))
db = client.test
try:
print("MongoDB version is %s" % client.server_info()['version'])
except pymongo.errors.OperationFailure as error:
print(error)
quit(1)
my_collection = db.goods
my_collection.delete_many({})
Результатом работы скрипта будет полная очистка коллекции:
Теперь поменяем в нашем скрипте формирования демо базы всего лишь одну функцию:
def get_random_features():
list=[]
ln=random.randint(1,10)
for i in range(ln):
list.append(generate_random_string(random.randint(3,15)))
return list
Теперь вместо объекта в поле features у нас коллекция, а не объект:
И теперь мы можем осуществить поиск по элементу коллекции:
my_cursor = my_collection.find({
"features": {"$eq": "hpwfslrwfsuqmue"}
})
Запрос найдет все документы, в которых в коллекции features встретится строка «hpwfslrwfsuqmue».
У меня выдало:
xinfirdgftc
Проверим:
Выражение $eq в фильтре означает «равно». Можно сравнивать на больше меньше, например, «меньше или равно» будет кодироваться как $lt:
import pymongo
from pymongo.server_api import ServerApi
client = pymongo.MongoClient("mongodb+srv://megabax:<Пароль>@cluster0.vwremdq.mongodb.net/?retryWrites=true&w=majority", server_api=ServerApi('1'))
db = client.test
try:
print("MongoDB version is %s" % client.server_info()['version'])
except pymongo.errors.OperationFailure as error:
print(error)
quit(1)
my_collection = db.goods
my_cursor = my_collection.find({
"price": {"$lt": 10}
})
for item in my_cursor:
print(item["name"], item["price"])
Эта программа выдаст список товаров, цена которых не превышает 10.
Более подробно о фильтрах и прочих возможностях mongjDB можно прочитать в документации MongoDB Documentation.
Comments
So empty here ... leave a comment!