Несколько месяцев назад мне понадобилась база данных документов для запланированного проекта Python. Не знаю, как так получилось, но погуглив, я умудрился не заметить ни одного существующего решения и пришёл к выводу, что единственный выход — написать своё.
Поскольку мне хотелось как можно быстрее получить работающее решение, я решил опираться на существующие реляционные базы данных, чтобы не беспокоиться о реализации хранения, поиска, транзакций и тому подобного.
В итоге мое творение приобрело достойный вид, и я решил написать о нем заметку здесь — может быть, кому-нибудь она окажется полезной.
Где взять
Для самых нетерпеливых:- страница проекта с документацией и ссылкой для скачивания - pypi.python.org/pypi/brain
- Git-репозиторий проекта — github.com/Мантикора/мозг
Сразу прошу прощения у всех ортодоксальных людей, которые до сих пор не могут решиться на переход даже на 2.6 - я, конечно, мог бы портировать свой модуль на 2.*, но поленился.
Как я уже говорил, в качестве нижнего слоя модуль использует обычную реляционную базу данных.
В настоящее время поддерживаются SQLite (тот, который поставляется с Python) и Postgre 8 (если установлен py-postgresql).
… и что с этим делать
Я предполагаю, что многие люди уже знакомы с базами данных документов, поэтому я буду краток.Итак, наше основное понятие — объект. Объект имеет уникальный идентификатор и ряд различных типов данных.
В моей базе данных данные представляют собой комбинацию простых типов — int, float, str, bytes и None — и сложных типов — dict и list. Уровень вложенности ограничен только реляционным движком, о причинах я расскажу позже.
Сам идентификатор объекта также может храниться в другом (или в том же) объекте.
Объекты можно создавать, удалять, а их содержимое можно изменять любым способом; и, конечно же, поиск необходимых объектов по заданным критериям.
Итак, предположим, что вы уже скачали и установили модуль.
Или даже просто подарили – не важно.
Для иллюстрации работы с модулем я просто скопирую сюда несколько примеров из документации (для тех, кому было лень пройти по ссылке выше).
Итак, подключим модуль и создадим соединение.
Для простоты будет использоваться реляционный механизм по умолчанию (SQLite) и база данных в памяти.
>>> import brain
>>> conn = brain.connect(None, None)
Теперь давайте создадим пару объектов.
Обратите внимание на вложенный список во втором объекте.
>>> id1 = conn.create({'a': 1, 'b': 1.345})
>>> id2 = conn.create({'id1': id1, 'list': [1, 2, 'some_value']})
Объекты можно читать целиком или выделить определенную область.
Во втором случае используется путь к нужным данным — просто список, где строка означает ключ в дикте, а число означает индекс в списке.
>>> print(conn.read(id1))
{'a': 1, 'b': 1.345}
>>> print(conn.read(id2, ['list']))
[1, 2, 'some_value']
Содержимое объекта можно изменить.
>>> conn.modify(id1, ['a'], 2)
>>> print(conn.read(id1))
{'a': 2, 'b': 1.345}
И наконец, нужный объект может быть найден.
>>> import brain.op as op
>>> objs = conn.search(['list', 0], op.EQ, 1)
>>> print(objs == [id2])
True
Используемое условие расшифровывается как «0-й элемент списка, находящегося в ключе 'dict' корневого словаря, равен 1».
И все это?
Не совсем.Для списков существует специальная команда вставки (которая работает почти так же, как ее эквивалент в Python).
Объекты и их части можно удалять (в том числе с помощью масок).
Условия поиска можно комбинировать с помощью логических операторов.
Ах да, транзакции тоже поддерживаются, есть простой RPC-сервер и кеширующее соединение (довольно глупое).
Обо всем этом вы можете прочитать в документации.
Что внутри?
Внутри все довольно просто.Для каждого уникального пути создается таблица с соответствующим именем (причем пути, отличающиеся только индексами в списках, используют одну и ту же таблицу).
Например, для таких данных, как {'key': [{'key2': 'val'}]}, значение 'val' будет храниться в таблице с именем "field.TEXT.key.key2" (пустое пространство между двумя точками говорит, что список находится по ключу 'key').
Кроме того, имеется одна большая таблица, в которой для каждого объекта записаны имеющиеся у него поля и их типы.
Таким образом, если вдруг что-то пойдет не так, данные можно будет восстановить, используя доступные инструменты работы с реляционными базами данных.
Это приводит к ограничению уровня вложенности хранимых структур данных — все зависит от максимальной длины имени таблицы, которую поддерживает реляционная база данных.
И что дальше?
Как я уже сказал, существующей версии базы данных вполне достаточно для моих целей.Но если вдруг кто-то подумает, что это творение может быть полезно кому-то еще, то я буду рад добавить необходимые функции.
И, конечно же, приветствуется любая конструктивная критика по коду/архитектуре/документации.
Теги: #python #sql #ddb #Chulan
-
Приглашаем Вас На Mskdotnet Meetup #24
19 Oct, 24 -
Ваша Фотография На Google.com
19 Oct, 24 -
Онлайн-Рейтинг Книг
19 Oct, 24 -
W3Cast №3
19 Oct, 24 -
Миграция Php На Java
19 Oct, 24 -
Skype 2.8 Gold Для Mac Os X
19 Oct, 24