安装
brew install redis
sudo pip3 install redis
安装:https://redis.io/docs/getting-started/installation/install-redis-on-mac-os/
如果安装报错:https://github.com/Homebrew/homebrew-core/issues/11134
使用
启动
# 默认端口是 6379
redis-server --port 6379
# 后台运行
redis-server --port 6379 --daemonize yes
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.set('name', 'runoob') # 设置 name 对应的值
r.get('name')
set(name, value, ex=None, px=None, nx=False, xx=False)
- ex - 过期时间(秒),过了这个时间后,值就变成None
- px - 过期时间(毫秒)
- nx - 如果设置为True,则只有name不存在时,当前set操作才执行
- xx - 如果设置为True,则只有name存在时,当前set操作才执行
# 批量get和set
r.mset({'k1': 'v1', 'k2': 'v2'})
r.mget("k1", "k2")
# 获取值,并且设置一个新值
r.getset("k1", "v3")
getrange 和 setrange
r.set("name", "abcde")
r.getrange("name", start=0, end=2)
# 得到 'abc'
r.setrange("name", offset=1, value="fff")
# 变成 'afffe'
# 删除
r.delete("name")
# 是否存在
r.exists("name")
# 模糊匹配
keys(pattern='')
# 设置超时时间
r.expire("list5", time=3)
# 重命名
rename(src, dst)
# 随机获取一个key
r.randomkey()
# 返回类型
r.type("set1")
操作二进制
setbit(name, offset, value)
getbit(name, offset)
bitcount(key, start=None, end=None)
# 获取name对应的值的二进制表示中 1 的个数
bitop(operation, dest, *keys)
# 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值
bitop("AND", 'new_name', 'n1', 'n2', 'n3')
# 把n1,n2,n3 做AND运算,然后把结果放入 new_name
r.strlen(key) # 对应的长度
r.incr(self, name, amount=1)
# name对应的数字自增1,如果不存在则初始化为 amount
r.incrbyfloat(self, name, amount=1.0)
# 效果同上,但是是浮点型
r.decr(self, name, amount=1)
# 自减
# 字符串追加
r.append(key="name", value="a")
hash相关
import redis
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
r.hset("hash1", "k1", "v1")
r.hset("hash1", "k2", "v2")
print(r.hkeys("hash1")) # 取hash中所有的key,['k1', 'k2']
print(r.hget("hash1", "k1")) # 单个取hash的key对应的值,
print(r.hmget("hash1", "k1", "k2")) # 多个取hash的key对应的值,['v1', 'v2']
# 批量set
hmset(name, mapping)
# 批量get
hmget(name, keys, *args)
# 取出所有kv
r.hgetall("hash1")
# 获取所有kv个数
r.hlen("hash1")
# 获取所有key
r.hkeys("hash1")
# 获取所有value
r.hvals("hash1")
# 判断是否存在
r.hexists("hash1", "k4")
# 删除一个键值对
r.hdel("hash1", "k1")
# 自增
r.hincrby(name, key, amount=1)
r.hincrbyfloat(name, key, amount=1.0)
# 分片读取
hscan(name, cursor=0, match=None, count=None)
redis-list
import redis
import time
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
# 增加,每个新的元素都添加到列表的最左边
r.lpush("list1", 11, 22, 33)
print(r.lrange('list1', 0, -1))
# 33,22,11
# 增加,每个新元素添加到右边
r.rpush("list2", 11, 22, 33)
print(r.llen("list2")) # 列表长度
print(r.lrange("list2", 0, 3)) # ['11', '22', '33']
# 往已经有的name的列表的左边添加元素,没有的话无法创建
lpushx(name,value)
redis-set
r.sadd("set1", 33, 44, 55, 66) # 往集合中添加元素,返回添加的个数
print(r.scard("set1")) # 集合的长度是4
print(r.smembers("set1")) # 获取集合中所有的成员
# 差集
r.sdiff("set1", "set2")
# 差集放入 set3
r.sdiffstore("set3", "set1", "set2")
# 交集
r.sinter("set1", "set2")
# 交集放入 set3
r.sinterstore("set3", "set1", "set2")
# 并集
r.sunion("set1", "set2")
# 并集放入 set3
r.sunionstore("set3", "set1", "set2")
# 是否属于
r.sismember("set1", 33)
# 把一个元素从一个集合移动到另一个集合
r.smove(src="set1", dst="set2", value=33)
# 随机删除一个元素
r.spop("set1")
# 删除指定的元素
r.srem("set2", 11)
redis-有序set
r.zadd("zset1", {"n1": 11, "n2": 22})
r.zadd("zset2", {'m1': 22, 'm2': 44})
print(r.zcard("zset1")) # 集合长度
print(r.zcard("zset2")) # 集合长度
print(r.zrange("zset1", 0, -1)) # 获取有序集合中所有元素
print(r.zrange("zset2", 0, -1, withscores=True)) # 获取有序集合中所有元素和分数
# 集合长度
r.zcard("zset1")
# 获取
r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
# 获取索引
zrank(name, value)
# 倒过来的索引
zrevrank(name, value)
# 删除
zrem(name, values)
# 根据索引,范围删除
zremrangebyrank(name, min, max)
# 根据分数范围删除
zremrangebyscore(name, min, max)
# 获取分数
zscore(name, value)
参考资料
https://www.runoob.com/w3cnote/python-redis-intro.html
ElasticSearch
- code:https://github.com/elastic/elasticsearch
- 官网:https://www.elastic.co/elasticsearch/
- 用Docker在本地部署:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker-cli-run-dev-mode
原理
底层原理:倒排索引。
传统的索引:
id | document |
---|---|
1001 | my name is zhang san |
1002 | my name is li si |
倒排索引: |keyword|ids| |–|–| name|1001,1002 zhang|1001 …|…
作用
- 提高了查询效率
- 可以模糊查询,例如大小写、时态
连接es
from elasticsearch import Elasticsearch
es = Elasticsearch(
"https://localhost:9200",
# ca_certs="/path/to/http_ca.crt",
verify_certs=False,
basic_auth=("<user>", "<password>")
)
es.info()
索引
# 创建索引
es.indices.create(index="index_name1")
# 查询索引(匹配)
es.indices.get(index="*")
# 查询索引(精确)
es.indices.get(index='index_name1')
# 返回索引(简洁)
es.indices.get(index="*").keys()
# 判断某个索引是否存在
es.indices.exists(index='index_name')
# 删除索引
es.indices.delete(index="index_name")
插入数据
es.index(index="index_name1", id=0, body={'name': 'jaychou', "age": 30, "sex": 'male'})
es.index(index="index_name1", id=1, body={'name': '我爱你中国', "age": 30, "sex": 'male'})
查询
切片查询:相当于limit
body = {
'from': 0, # 从0开始
'size': 20 # 返回20条
}
es.search(index='index_name1', body=body)
match:模糊查询,先分词,再匹配token
body = {
'query': { # 查询命令
'match': { # 查询方法:模糊查询(会被分词)。比如此代码,会查到包含:“我爱你”, “算法”的内容
'name': '我爱你算法'
}
},
'size': 20 # 不指定默认是10,最大值不超过10000
}
es.search(index='index_name1', body=body)
# 会返回 “我爱你中国”,因为
match_phrase:模糊查询,不分词,整体匹配token
body = {
'query': {
'match_phrase': {
'name': '我爱你算法'
}
}
}
term/terms,精准查询。
# 类似sql中的 where name='我爱你中国'
body = {
'query': {
'term': {
'name.keyword': '我爱你中国' # 注意这里要加 .keyword
}
}
}
# 类似 where name in (a, b,c...)
body = {
'query': {
'terms': {
'name.keyword': ['我爱你中国', 'I love China']
}
}
}
multi_match,多字段查询
# 查询多个字段中都包含指定内容的数据
body = {
"query":{
"multi_match":{
"query":"我爱你中国", # 指定查询内容,注意:会被分词
"fields":["ziduan1", "ziduan2"] # 指定字段
}
}
}
prefix,前缀查询
body = {
'query': {
'prefix': {
'ziduan.keyword': '我爱你' # 查询前缀是指定字符串的数据
}
}
}
# 注:英文不需要加keyword
wildcard,通配符查询;regexp,正则查询
body = {
'query': {
'wildcard': {
'ziduan1.keyword': '?爱你中*' # ?代表一个字符,*代表0个或多个字符
}
}
}
# 注:此方法只能查询单一格式的(都是英文字符串,或者都是汉语字符串)。两者混合不能查询出来。
body = {
'query': {
'regexp': {
'ziduan1': 'W[0-9].+' # 使用正则表达式查询
}
}
}
bool,多条件查询
# must:[] 各条件之间是and的关系
body = {
"query":{
"bool":{
'must': [{"term":{'ziduan1.keyword': '我爱你中国'}},
{'terms': {'ziduan2': ['I love', 'China']}}]
}
}
}
# should: [] 各条件之间是or的关系
body = {
"query":{
"bool":{
'should': [{"term":{'ziduan1.keyword': '我爱你中国'}},
{'terms': {'ziduan2': ['I love', 'China']}}]
}
}
}
# must_not:[]各条件都不满足
body = {
"query":{
"bool":{
'must_not': [{"term":{'ziduan1.keyword': '我爱你中国'}},
{'terms': {'ziduan2': ['I love', 'China']}}]
}
}
}
# bool嵌套bool
# ziduan1、ziduan2条件必须满足的前提下,ziduan3、ziduan4满足一个即可
body = {
"query":{
"bool":{
"must":[{"term":{"ziduan1":"China"}}, # 多个条件并列 ,注意:must后面是[{}, {}],[]里面的每个条件外面有个{}
{"term":{"ziduan2.keyword": '我爱你中国'}},
{'bool': {
'should': [
{'term': {'ziduan3': 'Love'}},
{'term': {'ziduan4': 'Like'}}
]
}}
]
}
}
}
exists,存在字段查询
body = {
'query': {
'exists': {'field': 'ziduan1'} # 查询存在ziduan1的数据
}
}
额外
对结果排序
body = {
"query":{
"match_all":{}
}
"sort":[{
"age":{ # 先根据age字段升序排序
"order":"asc" # asc升序,desc降序
}
},{
"name":{ # 后根据name字段升序排序
"order":"asc" # asc升序,desc降序
}
}],
}
删除符合条件的数据
es.delete_by_query(index='index_name', body=body)
参考:
- https://blog.csdn.net/sinat_38682860/article/details/107693969,
- https://blog.csdn.net/weixin_42182448/article/details/113655731
MongoDB
- 源码:https://github.com/mongodb/mongo
- 官网:https://www.mongodb.com
python3 -m pip3 install pymongo
dbm:轻量级KV存储
语法基本与 dict 一样
import dbm
db = dbm.open('db_file', 'c')
# C 读写,如存在则创建
# W 读写,如不存在,则不创建
# N 读写,总是创建一个新的空白文件
# 增
db['val'] = '1' # 值只能是string
# 查
print(db['val'])
# 删
del db['val']
print(db.keys())
# 保存,关闭
db.close()
参考
- 全球数据库排行榜:https://db-engines.com/en/ranking