此文参考cassandra driver 3.8.1文档,参考原文的结构,链接地址:
cassandra-driver-3.8.1
详细文档
确保安装正确的驱动模块(cassandra-driver),可以通过pip安装。
连接数据库(cassandra下同),必须确保有安装Cluster模块。正常情况下,本文中使用到的模块,安装 cassandra-driver中已有。
如果使用非标准的端口(9042)或使用SSL方式连接,或自定义一些驱动操作,还需要引入DCAwareRoundRobinPolicy模块
from cassandra.cluster import Cluster #引入Cluster模块
from cassandra.polices import DCAwareRoundRobinPolicy#引入DCAwareRoundRobinPolicy模块
cluster = Cluster()#连接本地数据库
cluster = Cluster(['127.0.0.1'])#连接本地数据库
cluster = Cluster(['1.1.1.1','1.1.1.2'])#连接两台机器的数据库
cluster = Cluster(['1.1.1.1', '1.1.1.2', '1.1.1.3'],
load_balancing_policy=DCAwareRoundRobinPolicy(local_dc='US_EAST'), port=8888)#连接三台机器的数据库,且指定端口为8888
创建了Cluster后,并不会自动连接上数据库,需要我们执行连接操作。
session = cluster.connect()#简单的连接
session = cluster.connect('keyspacename')#指定连接keyspace,相当于sql中use dbname
session.set_keyspace('otherkeyspace') #设置、修改keyspace
session.execute('use keyspacename')#设置、修改keyspace
查询操作使用execute(),将cql语句拼接作为参数传入即可。
rows = session.execute('select * from table1') #查询所有列
rows = session.execute('select name,age,email from table1')#查询指定列
for row in rows: #遍历查询的结果
print(row.name+row.age+row.email)
print(row[0]+row[1]+row[2])
for (name,age,email) in rows:#遍历查询的结果
print(name+age+email)
支持两种传参查询操作:位置和名字。
位置
使用%s来传递
session.execute(
"""
INSERT INTO users (name, credits, user_id)
VALUES (%s, %s, %s)
""",
("hmh", 30, uuid.uuid1())
)
这里对所有类型的参数都使用%s,如果想传入字符%,使用%%。在传递序列时,必须有第二值(第一个值后面加,)。
session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # 末尾要加,
session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])
名字
可以使用相同名称的占位符。通常只用这种方式传递数据值,像keyspace名、表名、列名必须在开始就设定好。
session.execute(
"""
INSERT INTO users (name, credits, user_id, username)
VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
""",{'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()})
#注意占位符(name)使用了两次
驱动支持异步查询,对应方法是execute_async()。相比于等侍查询完成返回结果,这个方法会立即返回一个ResponseFuture对象。有两个方法可以从ResponseFuture对象中取得结果。
from cassandra import ReadTimeout # 引入ReadTimeout模块
query = "SELECT * FROM users WHERE user_id=%s"
future = session.execute_async(query, [user_id])#异步查询做其它工作
try:
rows = future.result()#读查询结果
user = rows[0]
print(user.name+user.age)
except ReadTimeout:#出现异常的情况
log.exception("Query timed out:")
还可以同时执行多个查询:
futures = []
query = "SELECT * FROM users WHERE user_id=%s"
for user_id in ids_to_fetch:#将所有查询加入列表
futures.append(session.execute_async(query, [user_id])
#执行其它操作
for future in futures:
rows = future.result()
print(rows[0].name)
def handle_success(rows):#定义成功操作
user = rows[0]
try:
process_user(user.name, user.age, user.id)
except Exception:
log.error("Failed to process user %s", user.id)
# don't re-raise errors in the callback
def handle_error(exception):#定义错误处理
log.error("Failed to fetch user info: %s", exception)
future = session.execute_async(query)#执行异步查询
future.add_callbacks(handle_success, handle_error)
需要注意两点:
1、任何回调函数内部的异常将会被记录并忽略处理;
2、回调运行在事件循环线程,因此长任务操作将会阻止其它请求的处理。
一致性等级是用来确定一次成功的查询,需要多少数量副本对查询有响应。默认的查询的一致性等级是ConsistencyLevel.LOCAL_ONE,当然你可以通过Session.default_consistency_level设定想要等级。为了为每个请求指定不同的一致性等级,需要包装查询在SimpleStatement中:
from cassandra import ConsistencyLevel
from cassandra.query import SimpleStatement
query = SimpleStatement(
"INSERT INTO users (name, age) VALUES (%s, %s)",
consistency_level=ConsistencyLevel.QUORUM)#设置等级水平
session.execute(query, ('John', 42))#执行查询
Prepared Statements是由Cassandra解析的查询,然后保存供以后使用。 当驱动程序使用Prepared Statements时,它只需要发送要绑定的参数的值。 这会降低Cassandra内的网络流量和CPU利用率,因为Cassandra不必每次重新解析查询。使用Session.prepare()来准备查询:
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")#准备语句使用'?'表示占位
users = []
for user_id in user_ids_to_query:
user = session.execute(user_lookup_stmt, [user_id])
users.append(user)
prepare()返回一个可用于替代SimpleStatement实例或字面字符串查询的PreparedStatement实例。 它将针对所有节点自动准备,并且必要时,驱动程序可以处理针对新节点和重新启动的节点的重新准备。
注意,准备语句的占位符是’?’字符, 这与简单的、非准备的语句不同(尽管驱动程序的未来版本可能使用相同的占位符)。
对Prepared Statements设置一致性等级,有两个方法:
from cassandra import ConsistencyLevel
cluster = Cluster()
session = cluster.connect("mykeyspace")
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")#查询准备语句
user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM#prepare语句设置一致性等级
user1 = session.execute(user_lookup_stmt, [user_id1])[0]
user2 = session.execute(user_lookup_stmt, [user_id2])[0]
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")#查询准备语句
user3_lookup = user_lookup_stmt.bind([user_id3])#绑定参数
user3_lookup.consistency_level = ConsistencyLevel.ALL
user3 = session.execute(user3_lookup)