Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Васильев Ю. - Python для data science (Библиотека программиста) - 2023.pdf
Скачиваний:
7
Добавлен:
07.04.2024
Размер:
7.21 Mб
Скачать

Базы данных NoSQL      125

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

Базы данных NoSQL

Базы данных NoSQL, или нереляционные базы данных, не требуют заранее определенной схемы организации хранимых данных; кроме того, они не поддерживают стандартные операции реляционных БД, например объединение. Зато они предоставляют способы хранения информации с большей структурной гибкостью, что облегчает работу с большими объемами данных. Хранилища «ключ — значение» (один из типов баз данных NoSQL) позволяют хранить и извлекать данные в виде пар «ключ — значение», например время — событие. До- кументно-ориентированные базы данных — еще один тип баз данных NoSQL — предназначены для работы с контейнерами данных с гибкой структурой, такими как документы JSON. Они позволяют хранить всю информацию, относящуюся к определенному объекту, в виде одной записи в БД, а не разбивать данные по нескольким таблицам, как в реляционных базах.

Хотя базы данных NoSQL существуют не так давно, как их реляционные аналоги, они быстро набрали популярность, поскольку позволяют разработчикам хранить данные в простых понятных форматах и не требуют высокой квалификации для доступа к данным и их обработки. Благодаря своей гибкости, они особенно хорошо подходят для приложений реального времени и для приложений, обрабатывающих большие объемы данных, таких как Google Gmail или LinkedIn.

ПРИМЕЧАНИЕ

О происхождении термина NoSQL нет единого мнения. Одни считают, что оно обозначает non-SQL, а другие — что название происходит от not only SQL. Уместныобаварианта:базыданныхNoSQLхранятданныевформате,отличном от реляционных (SQL) таблиц, и в то же время многие из этих баз данных поддерживают запросы типа SQL.

Хранилища «ключ — значение»

Хранилище «ключ — значение» — это база данных, которая хранит пары «ключ — значение», подобно словарю Python. Хороший пример такого типа хранилищ —

126      Глава 5. Работа с базами данных

Redis (сокращение от Remote Dictionary Service). Redis поддерживает такие команды, как GET, SET и DEL, для доступа к парам «ключ — значение» и выполнения операций с ними, как показано в простом примере ниже:

$ redis-cli

127.0.0.1:6379> SET emp1 "Maya Silver"

OK

127.0.0.1:6379> GET emp1 "Maya Silver"

Здесь мы используем команду SET для создания ключа emp1 со значением Maya Silver, а затем применяем GET для получения значения через его ключ.

Установка Redis

Чтобы самостоятельно изучить Redis, необходимо установить его. Более подробную информацию можно найти на странице быстрого запуска Redis1. После установки сервера Redis в систему также потребуется установить redis-py, библиотеку­ Python, которая позволяет взаимодействовать с Redis из Pythonскрипта. Это можно сделать с помощью команды pip:

$ pip install redis

Затем импортируйте redis-py в свой скрипт командой import redis.

Доступ к Redis с помощью Python

Ниже приведен простой пример доступа к серверу Redis с помощью Python из библиотеки redis-py:

> import redis

> r = redis.Redis()

> r.mset({"emp1": "Maya Silver", "emp2": "John Jamison"})

True

> r.get("emp1") b'Maya Silver'

1 https://redis.io/topics/quickstart

Базы данных NoSQL      127

Используем метод redis.Redis()для установки соединения с сервером Redis . Поскольку параметры метода не указаны, они будут установлены по умолчанию, то есть предполагается, что сервер запущен на локальной машине:

host='localhost', port=6379 и db=0.

ПРИМЕЧАНИЕ

Redis нумерует базы данных с помощью индексации с нуля. Новые соединения по умолчанию используют базу данных с индексом 0.

После установки соединения используем метод mset(), чтобы задать несколько пар «ключ — значение» (m — сокращение от multiple). Сервер возвращает True, если данные успешно сохранены. Затем с помощью метода get() можно получить значение любого из хранимых ключей .

Как и любая другая БД, Redis позволяет сохранять добавляемые данные. Это означает, что по ключу можно будет получить соответствующее значение в другой сессии Python или в другом скрипте. Redis также позволяет установить флаг истечения срока действия (expire flag) для ключа при задании пары. Он будет указывать, как долго ее следует хранить. Это может быть особенно полезно в приложениях реального времени, где входные данные теряют актуальность через какое-то время. Например, если вы разрабатываете приложение для заказа такси, вам, возможно, потребуется хранить данные о доступности каждой отдельной машины. Поскольку эти данные будут часто меняться, необходимо ограничить срок их действия. Вот как можно это сделать:

--snip--

>from datetime import timedelta

>r.setex("cab26", timedelta(minutes=1), value="in the area now")

True

Используем метод setex()для задания пары «ключ — значение», которая будет автоматически удалена из базы данных через определенное время. В нем мы указываем время истечения срока действия в виде объекта timedelta. Другой способ — задать число в секундах.

До сих пор мы рассматривали только простые пары «ключ — значение», но в Redis­ можно хранить и несколько фрагментов информации об одном и том же объекте, как показано ниже:

128      Глава 5. Работа с базами данных

>cabDict = {"ID": "cab48", "Driver": "Dan Varsky", "Brand": "Volvo"}

>r.hmset("cab48", cabDict)

>r.hgetall("cab48")

{'Cab': 'cab48', 'Driver': 'Dan Varsky', 'Brand': 'Volvo'}

Сначала мы определяем словарь Python, который может содержать произвольное количество пар «ключ — значение». Затем отправляем весь этот словарь в базу данных, сохраняя его под ключом cab48 с помощью функции hmset() (h — сокращение от hash). После этого используем функцию hgetall() для получения всех пар «ключ — значение», хранящихся под ключом cab48.

Документоориентированные базы данных

Документоориентированная база данных хранит каждую запись как отдельный документ. Вместо соответствия заранее определенной схеме, такой как поля таблицы реляционной базы данных, каждый документ в документоориентированной БД может иметь свою собственную структуру. Подобная гибкость сделала эти базы данных наиболее популярным типом БД NoSQL. А самая популярная документоориентированная база данных — MongoDB. Она предназначена для управления коллекциями документов вида JSON. В этом разделе мы посмотрим, как с ней работать.

Установка MongoDB

Существует несколько способов работы с MongoDB. Первый — установить ее в свою систему. Чтобы узнать, как это сделать, обратитесь к документации MongoDB1. Другой вариант не требует установки. Он заключается в создании бесплатной платформы с MongoDB с помощью MongoDB Atlas. Для этого необходимо зарегистрироваться на сайте MongoDB Atlas2.

Прежде чем начать работу с базой данных MongoDB из Python, необходимо установить PyMongo, официальный драйвер Python для MongoDB. Это можно сделать с помощью команды pip:

$ pip install pymongo

1 https://docs.mongodb.com/manual/installation

2 https://www.mongodb.com/cloud/atlas/register

Базы данных NoSQL      129

Доступ к MongoDB с помощью Python

Первый шаг к работе с MongoDB на Python — установка соединения с сервером БД через объект PyMongo MongoClient, как показано ниже:

>from pymongo import MongoClient

>client = MongoClient('connection_string')

Строкой подключения (connection_string) может быть URI-адрес подключения к MongoDB, например mongodb://localhost:27017. Для ее использования необходимо установить MongoDB в локальной системе. А при использовании MongoDB Atlas потребуется вставить строку подключения, предоставленную Atlas. Подробнее см. на странице Connect via Driver документации Atlas1, а также на странице Connection String URI Format2.

Вместо строки подключения можно указать хост и порт в виде отдельных параметров конструктора MongoClient():

> client = MongoClient('localhost', 27017)

Один экземпляр MongoDB может поддерживать несколько баз данных, поэтому после установки соединения с сервером необходимо указать ту базу, с которой вы хотите работать. MongoDB не предоставляет отдельную команду для создания БД, поэтому для создания новой базы данных и доступа к существующей используется один и тот же синтаксис. Например, чтобы создать БД с именем sampledb (или получить к ней доступ, если она уже существует), можно использовать синтаксис обращения к словарю:

> db = client['sampledb']

или синтаксис обращения к атрибуту:

> db = client.sampledb

В отличие от реляционных баз данных, MongoDB не хранит данные в таблицах. Документы группируются в коллекции. Создание коллекции и доступ к ней аналогичны созданию БД и доступу к ней:

1 https://docs.atlas.mongodb.com/driver-connection

2 https://docs.mongodb.com/manual/reference/connection-string

130      Глава 5. Работа с базами данных

> emps_collection = db['emps']

Эта команда создаст коллекцию emps в базе данных sampledb, если она еще не была создана. Затем можно использовать метод insert_one() для вставки документа в коллекцию. В примере ниже мы вставляем документ emp, отформатированный как словарь:

> emp = {"empno": 9001,

...

"empname": "Jeff

Russell",

...

"orders": [2608,

2617, 2620]}

> result = emps_collection.insert_one(emp)

При вставке документа в него автоматически добавляется поле "_id". Значение этого поля формируется таким образом, чтобы оно было уникальным в рамках всей коллекции.

Доступ к ID можно получить через поле inserted_id объекта, возвращаемого командой insert_one():

> result.inserted_id ObjectId('69y67385ei0b650d867ef236')

Теперь БД содержит данные, но как их запрашивать? Самый распространенный способ — запрос методом find_one(), который возвращает единственный документ, соответствующий критериям поиска:

>emp = emps_collection.find_one({"empno": 9001})

>print(emp)

Как видите, find_one()не требует ID документа, он был автоматически добавлен при вставке. Вместо этого можно запросить конкретные элементы, которым, как предполагается, соответствует документ.

Результат будет выглядеть примерно так:

{

u'empno': 9001,

u'_id': ObjectId('69y67385ei0b650d867ef236'), u'empname': u'Jeff Russell',

u'orders': [2608, 2617, 2620]

}