【python】redis/ES/dbm



2022年07月09日    Author:Guofei

文章归类: 0xb0_Python语法    文章编号: 1265

版权声明:本文作者是郭飞。转载随意,但需要标明原文链接,并通知本人
原文链接:https://www.guofei.site/2022/07/09/redis.html


安装

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 …|…

作用

  1. 提高了查询效率
  2. 可以模糊查询,例如大小写、时态

连接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

您的支持将鼓励我继续创作!