Предполагается, что Cassandra уже установлена и работает, и в ней есть база TestKeyspace и таблица users, созданные в статье Apache Cassandra: описание директорий, язык CQL, утилита cqlsh.
Содержание
Установка драйвера
Для работы с Cassandra из Python требуется cassandra-driver, который можно установить из PIP.
Для установки PIP в Debian — выполняем:
# aptitude install python-pip
И устанавливаем драйвер:
# pip install cassandra-driver
Что бы проверить — запускаем консоль Python:
>>> from cassandra.cluster import Cluster
>>> cluster = Cluster()
>>> session = cluster.connect('testkeyspace')
Что бы подключиться к кластеру по IP — укажите один или несколько адресов:
>>> cluster = Cluster(['127.0.0.1', '192.168.1.0'])
>>> session = cluster.connect('testkeyspace')
Подробнее — cassandra.cluster.
Выполнение запросов к базе
Посмотреть содержимое таблицы users:
>>> session = cluster.connect('testkeyspace')
>>> result = session.execute("select * from users")
>>> print result
[]
Добавим запись:
>>> session.execute("INSERT INTO users (id, name, login, group) VALUES (1, 'User', 'setevoy', 'wheel')")
>>> result = session.execute("select * from users")[0]
>>> print result
Row(id=1, group=u'wheel', login=u'setevoy', name=u'User')
Вывести только отдельные поля:
>>> result = session.execute("select * from users")[0]
>>> print result.login, result.name
setevoy User
Или так:
>>> result = session.execute("select * from users")
>>> for x in result: print x.id
...
1
В запросы можно передавать параметры из переменных, например:
>>> name, login, group = 'newuser', 'newlogin', 'newgroup'
>>> session.execute("INSERT INTO users (id, name, login, group) VALUES (2, %s, %s, %s)", (name, login, group))
>>> session.execute("select * from users")
[Row(id=1, group=u'wheel', login=u'setevoy', name=u'User'), Row(id=2, group=u'newgroup', login=u'newlogin', name=u'newuser')]
Учтите, что в данном случае необходимо использовать %s для всех типов данных, а не только строк.
То же, но с помощью словаря:
>>> dict = {'name':'secondname','login':'secondlogin','group':'secondgroup',}
>>> dict.values()
['secondlogin', 'secondgroup', 'secondname']
>>> session.execute("""INSERT INTO users (id, name, login, group) VALUES (2, %(name)s, %(login)s, %(group)s)""", dict)
>>> session.execute("select * from users")
[Row(id=1, group=u'wheel', login=u'setevoy', name=u'User'), Row(id=2, group=u'secondgroup', login=u'secondlogin', name=u'secondname')]
Типы данных
| Тип в Python | Тип в CQL |
|---|---|
| None | NULL |
| bool | boolean |
| float |
float
double
|
|
int
long
|
int
bigint
varint
counter
|
| decimal.Decimal | decimal |
|
str
unicode
|
ascii
varchar
text
|
|
buffer
bytearray
|
blob |
| date | date |
| datetime | timestamp |
| time | time |
|
list
tuple
generator
|
list |
|
set
frozenset
|
set |
|
dict
OrderedDict
|
map |
| uuid.UUID |
timeuuid
uuid
|
Асинхронные запросы
Драйвер так же поддерживает выполнение асинхронных запросов с помощью execute_async(). Вместо того, что бы ждать окончания запроса и вернуть строку результата по окончанию выполнения — этот метод практически сразу возвращает объект ResponseFuture.
Например:
>>> from cassandra import ReadTimeout
>>> query = "SELECT * FROM users"
>>> future = session.execute_async(query)
>>> try:
... rows = future.result()
... for user in rows:
... print user.name, user.group
... except ReadTimeout:
... print('ERROR: query timed out')
...
User wheel
secondname secondgroup
Так же можно подключать функции «обратной связи», с помощью методов add_callback(), add_errback() и add_callbacks():
>>> def handle_success(rows):
... try:
... for user in rows:
... print user.name, user.group
... except Exception as e:
... print 'ERROR: %s' % e
...
>>> def handle_error(exception):
... print('Failed to fetch user info: %s' % exception)
...
>>> future = session.execute_async(query)
>>> future.add_callbacks(handle_success, handle_error)
User wheel
secondname secondgroup
Изменение Consistency Level
Consistency Level — «уровень согласованности» в Cassandra, который определяет сколько нод будут опрошены для получения результата, который будет считаться успешно завершённым.
По умолчанию используется ConsistencyLevel.ONE. Если хотите изменить этот параметр — используйте для вашего запроса класс SimpleStatement:
>>> from cassandra import ConsistencyLevel
>>> from cassandra.query import SimpleStatement
>>> query = SimpleStatement(
... "INSERT INTO users (id, name, login, group) VALUES (%s, %s, %s, %s)",
... consistency_level=ConsistencyLevel.QUORUM)
>>> session.execute(query, (3, 'name3', 'login3', 'group3'))
>>> session.execute('select * from users')
[Row(id=1, group=u'wheel', login=u'setevoy', name=u'User'), Row(id=2, group=u'secondgroup', login=u'secondlogin', name=u'secondname'), Row(id=3, group=u'group3', login=u'login3', name=u'name3')]
Подготовленные запросы
Prepared statements передаются Cassandra и сохраняются в ней для дальнешего выполнения. Когда дайвер использует такой подготовленный запрос — ему остаётся только передать значения параметров. Это позволяет снизить трафик и нагрузку на CPU, так как Cassandra не будет каждый раз парсить весь запрос заново.
Что бы подготовить такой запрос — используйте Session.prepare():
>>> user_lookup_stmt = session.prepare("SELECT * FROM users WHERE id=?")
>>> users = []
>>> user_ids_to_query = range(1,4)
>>> for user_id in user_ids_to_query:
... user = session.execute(user_lookup_stmt, [user_id])
... users.append(user)
...
>>> print users
[[], [Row(id=1, group=u'wheel', login=u'setevoy', name=u'User')], [Row(id=2, group=u'secondgroup', login=u'secondlogin', name=u'secondname')], [Row(id=1, group=u'wheel', login=u'setevoy', name=u'User')], [Row(id=2, group=u'secondgroup', login=u'secondlogin', name=u'secondname')], [Row(id=3, group=u'group3', login=u'login3', name=u'name3')]]
Ссылки по теме: