分享

Python操作MongoDB和Redis

 福兮007 2023-09-28 发布于上海

1. python对mongo的常见CURD的操作

 

1.1 mongo简介

mongodb是一个nosql数据库,无结构化、和去中心化。

那为什么要用mongo来存呢?

  1. 首先、数据关系复杂,没有表连接,结构化弱。

  2. 然后、利用mongo全文索引查找方便

  3. 最好、数据不重要,记录的日志数据库。意外丢失风险可以接受

安装:python3 -m pip3 install pymongo

 

 

1.2 python使用pymongo的简单CURD操作

1.2.1 创建一个数据库

创建数据库需要使用 MongoClient 对象,并且指定连接的 URL 地址和要创建的数据库名。

实例: 创建数库(连接数据库)user_info

import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
USER_MONGO = mongo_client['user_info']

注意:

在 MongoDB 中,数据库只有在内容插入后才会创建! 就是说,数据库创建后要创建集合(数据表)并插入一个文档(记录),数据库才会真正创建。

1.2.2 判断数据库是否存在

可以读取 MongoDB 中的所有数据库,并判断指定的数据库是否存在

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
USER_MONGO = mongo_client['user_info']
# 获取取数据库中的所有数据库
db_list = mongo_client.list_database_names()
if 'user_info' in db_list:
    print('数据库已存在')
else:
    print('数据库不存在')
复制代码

注意:

database_names 在最新版本的 Python 中已废弃,Python3.7+ 之后的版本改为了 list_database_names()。

1.2.3 pymongo创建集合

MongoDB 中的集合类似 SQL 的表。MongoDB 使用数据库对象来创建集合。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
my_watch = my_db['Asimov']
print(my_watch)
复制代码

注意:

在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。

1.2.4 判断集合是否已经存在

我们可以读取 MongoDB 数据库中的所有集合,并判断指定的集合是否存在:

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
my_watch = my_db['Asimov']
print(my_watch)

# 获取当前数据库中的所有表
col_list = my_db.list_collection_names()
print(col_list)
if 'my_watch' in col_list:
    print('集合已经存在')
else:
    print('集合不存在')
复制代码

 

1.3 Python Mongodb数据插入

1.3.1 插入一条数据

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

my_dict = {"name": "xiaoming", "age": 10000}

x = user.insert_one(my_dict)
print(x.inserted_id)  # 返回id字段
print(x)

# 5c808602707dc3863025ba3b
# <pymongo.results.InsertOneResult object at 0x000001F3C6764F48>
复制代码

如果我们在插入文档时没有指定 _id,MongoDB 会为每个文档添加一个唯一的 id

1.3.2 插入多条数据

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

my_list = [
    {"name": "xiaohua", "age": 18},
    {"name": "xiaoyang", "age": 20},
    {"name": "xiaoli", "age": 10},
]

x = user.insert_many(my_list)
print(x.inserted_ids)  # 返回id字段
print(x)

# [ObjectId('5c8086f1707dc385485a7dce'), ObjectId('5c8086f1707dc385485a7dcf'), ObjectId('5c8086f1707dc385485a7dd0')]
# <pymongo.results.InsertManyResult object at 0x000002305991BF48>
复制代码

1.3.3 插入指定 _id 的多个文档

我们也可以自己指定 id,插入,以下实例我们在 site2 集合中插入数据,_id 为我们指定的:

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

my_list = [
    {'_id': 1, "name": "xiaoxiong", "age": 18},
    {'_id': 2, "name": "xiaomao", "age": 20},
]

x = user.insert_many(my_list)
print(x.inserted_ids)  # 返回id字段

# [1, 2]
复制代码

 

1.4 Python Mongodb文档查询操作

MongoDB 中使用了 find 和 find_one 方法来查询集合中的数据,它类似于 SQL 中的 SELECT 语句。

复制代码
> use user_info
switched to db user_info
> db.dep.find()
{ "_id" : ObjectId("5c808503707dc381ec13b78e"), "name" : "xiaoming", "age" : 10000 }
{ "_id" : ObjectId("5c808602707dc3863025ba3b"), "name" : "xiaoming", "age" : 10000 }
{ "_id" : ObjectId("5c8086f1707dc385485a7dce"), "name" : "xiaohua", "age" : 18 }
{ "_id" : ObjectId("5c8086f1707dc385485a7dcf"), "name" : "xiaoyang", "age" : 20 }
{ "_id" : ObjectId("5c8086f1707dc385485a7dd0"), "name" : "xiaoli", "age" : 10 }
{ "_id" : 1, "name" : "xiaoxiong", "age" : 18 }
{ "_id" : 2, "name" : "xiaomao", "age" : 20 }
复制代码

1.4.1 查询一条数据

find_one()

x = user.find_one()
print(x)

# {'_id': ObjectId('5c808503707dc381ec13b78e'), 'name': 'xiaoming', 'age': 10000}

1.4.2 查询所有数据

find()

复制代码
for i in user.find():
    print(i)

# {'_id': ObjectId('5c808503707dc381ec13b78e'), 'name': 'xiaoming', 'age': 10000}
{'_id': ObjectId('5c808602707dc3863025ba3b'), 'name': 'xiaoming', 'age': 10000}
{'_id': ObjectId('5c8086f1707dc385485a7dce'), 'name': 'xiaohua', 'age': 18}
{'_id': ObjectId('5c8086f1707dc385485a7dcf'), 'name': 'xiaoyang', 'age': 20}
{'_id': ObjectId('5c8086f1707dc385485a7dd0'), 'name': 'xiaoli', 'age': 10}
{'_id': 1, 'name': 'xiaoxiong', 'age': 18}
{'_id': 2, 'name': 'xiaomao', 'age': 20}
复制代码

1.4.3 查询指定字段数据

find() 方法来查询指定字段的数据,将要返回的字段对应值设置为 1。

复制代码
for i in user.find({}, {"_id": 0, "name": 1, "age": 1}):
    print(i)

#{'name': 'xiaoming', 'age': 10000}
{'name': 'xiaoming', 'age': 10000}
{'name': 'xiaohua', 'age': 18}
{'name': 'xiaoyang', 'age': 20}
{'name': 'xiaoli', 'age': 10}
{'name': 'xiaoxiong', 'age': 18}
{'name': 'xiaomao', 'age': 20}
复制代码

注意:

除了 _id 你不能在一个对象中同时指定 0 和 1,如果你设置了一个字段为 0,则其他都为 1,反之亦然。

1.4.4 根据指定条件查询

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

myquery = {"name": "xiaoxiong"}

mydoc = user.find(myquery)
for x in mydoc:
    print(x)

# {'_id': 1, 'name': 'xiaoxiong', 'age': 18}
复制代码

1.4.5 高级查询

查询的条件语句中,我们还可以使用修饰符。

如读取 age 字段中值大于 18的数据,大于的修饰符条件为 {"$gt": 18} :

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

myquery = {"age": {"$gt": 18}}

mydoc = user.find(myquery)
for x in mydoc:
    print(x)
复制代码
输出

1.4.6 使用正则表达式查询

使用正则表达式作为修饰符。正则表达式修饰符只用于搜索字符串的字段。

如读取 name 字段中第一个字母为 "x" 的数据,正则表达式修饰符条件为 {"$regex": "^x"} :

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

myquery = {"name": {"$regex": "^x"}}

mydoc = user.find(myquery)
for x in mydoc:
    print(x)
复制代码
输出

1.4.7 返回指定条数记录

要对查询结果设置指定条数的记录可以使用 limit() 方法,该方法只接受一个数字参数。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

mydoc = user.find().limit(3)
for x in mydoc:
    print(x)
复制代码
输出

 

1.5 Python Mongodb 修改文档

1.5.1 MongoDB 中使用 update_one() 方法修改文档中的记录。

该方法第一个参数为查询的条件,第二个参数为要修改的字段。如果查出两条数据则只会修改第一条。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

myquery = {'age': 20}
newvalue = {'$set': {'age': 30}}

user.update_one(myquery, newvalue)

for i in user.find():
    print(i)
复制代码
输出

1.5.2 修改所有匹配到的记录,可以使用 update_many()。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

myquery = {'name': {'$regex': 'x'}}
newvalue = {'$set': {'age': 30}}

data = user.update_many(myquery, newvalue)

print('文档修改数量:', data.modified_count)
for i in user.find():
    print(i)
复制代码
输出

 

1.6 Python Mongodb 排序

db

sort() 方法可以指定升序或降序排序。

sort() 方法第一个参数为要排序的字段,第二个字段指定排序规则,1 为升序,-1 为降序,默认为升序。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

# mydoc = user.find().sort('age')
mydoc = user.find().sort('age',-1)
for i in mydoc:
    print(i)
复制代码
升序输出
降序输出

 

1.7 Python Mongodb 删除数据

1.7.1 delete_one() 方法来删除一个文档,该方法第一个参数为查询对象,指定要删除哪些数据。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

myquery = {"name":'xiaoming'}

user.delete_one(myquery)

for i in user.find():
    print(i)
复制代码
输出

1.7.2  delete_many() 方法来删除多个文档,该方法第一个参数为查询对象,指定要删除哪些数据。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

myquery = {"age": {'$gt': 18}}

user.delete_many(myquery)

for i in user.find():
    print(i)
复制代码
输出

1.7.3 删除集合中的所有文档

delete_many() 方法如果传入的是一个空的查询对象,则会删除集合中的所有文档:

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

data = user.delete_many({})

for i in user.find():
    print(i)
复制代码
输出

1.7.4 删除集合

drop() 方法来删除一个集合。

复制代码
import pymongo

mongo_client = pymongo.MongoClient(host='192.168.102.100', port=27017)
my_db = mongo_client['user_info']
# 获取取数据库中对应表
user = my_db['dep']

user.drop()
复制代码
输出

 

2. python对redis的常见操作

 我实践中主要使用redis作为消息队列。实际最佳场景为做缓存使用,效率高。redis是一个key-value结构的数据库,value的格式可以使string,set,list,map(即python里面的dict),sorted set(有序集合)

安装:

  pip install redis

 

2.1 初始化

2.1.1 直接连接

复制代码
import redis

r = redis.StrictRedis(host='192.168.102.100', port=6379)
r.set('one', 'first')
print(r.get('one'))

# b'first'
'''
参数: set(name, value, ex=None, px=None, nx=False, xx=False) ex,过期时间(秒) px,过期时间(毫秒) nx,如果设置为True,则只有name不存在时,当前set操作才执行,同setnx(name, value) xx,如果设置为True,则只有name存在时,当前set操作才执行
'''
#批量设置值
r.mset(name1='zhangsan', name2='lisi')
#或
r.mget({"name1":'zhangsan', "name2":'lisi'})
复制代码

2.1.2 redis 连接池连接
redis使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

复制代码
import redis

pool = redis.ConnectionPool(host='192.168.102.100', port=6379)
r = redis.Redis(connection_pool=pool)
r.set('two', 'second')
r.set('three', 'third')
print(r.get('two'))
print(r.get('three')

# b'second'
# b'third'
#批量获取
print(r.mget("name1","name2"))
#或
li=["name1","name2"]
print(r.mget(li))

#设置新值,打印原值
print(r.getset("name1","wangwu")) #输出:zhangsan
print(r.get("name1")) #输出:wangwu

#根据字节获取子序列
r.set("name","zhangsan")
print(r.getrange("name",0,3))#输出:zhan

#修改字符串内容,从指定字符串索引开始向后替换,如果新值太长时,则向后添加
r.set("name","zhangsan")
r.setrange("name",1,"z")
print(r.get("name")) #输出:zzangsan
r.setrange("name",6,"zzzzzzz")
print(r.get("name")) #输出:zzangszzzzzzz
 
复制代码

2.1.3 redis pipeline机制

可以在一次请求中执行多个命令,这样避免了多次的往返时延,并且默认情况下一次pipline 是原子性操作。

复制代码
import redis

pool = redis.ConnectionPool(host='192.168.102.100', port=6379)
r = redis.Redis(connection_pool=pool)
pipe = r.pipeline()
pipe.set('two', 'second')
pipe.set('three', 'third')
pipe.execute()
复制代码

2.1.4 string的存取

r.set("key1","value1")   
r.get("key1")

r.delete("key1") 

2.1.5 dict的存取

#
r.hset("usr1","name","kevin")
r.hset("usr1","age","18")
#
d=r.hgetall("usr1")

hgetall()方法会返回字典类型{"name":"kevin","age":"18"}

2.1.6 set(即无需的列表)存取

r.sadd("key1","value1","value2","value3")

r.smembers("key1")

2.1.7 list的存取

rpush()添加元素,llen()查看列表长度,ltrim()修剪列表,只保留起始下标到结束下标之间的数据,lrange(),为查找数据,查找出起始下标到结束下标之间的数据,返回的数据类型为list,如果结束下标小于起始下标,返回全部

r.rpush('log', 'log11')
r.rpush('log', 'log22')
r.rpush('log', 'log33')
print(r.llen('log'))
print(r.ltrim('log', 0, 3))
print(r.lrange('log', 0, -1))
输出

linsert(name, where, refvalue, value))

复制代码
# 在name对应的列表的某一个值前或后插入一个新值
r.linsert("list_name","BEFORE","2","SS")#在列表内找到第一个元素2,在它前面插入SS

'''
参数:
     name: redis的name
     where: BEFORE(前)或AFTER(后)
     refvalue: 列表内的值
     value: 要插入的数据
'''
复制代码

r.lset(name, index, value)

#对list中的某一个索引位置重新赋值
r.lset("list_name",0,"bbb")

r.lrem(name, value, num)

复制代码
#删除name对应的list中的指定值
r.lrem("list_name","SS",num=0)

''' 
参数:
    name:  redis的name
    value: 要删除的值
    num:   num=0 删除列表中所有的指定值;
           num=2 从前到后,删除2个;
           num=-2 从后向前,删除2个
'''
复制代码

lpop(name)

#移除列表的左侧第一个元素,返回值则是第一个元素
print(r.lpop("list_name"))

lindex(name, index)

#根据索引获取列表内元素
print(r.lindex("list_name",1))

lrange(name, start, end)

#分片获取元素
print(r.lrange("list_name",0,-1))

ltrim(name, start, end)

#移除列表内没有在该索引之内的值
r.ltrim("list_name",0,2)

rpoplpush(src, dst)

# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
#src 要取数据的列表
#dst 要添加数据的列表

2.1.8 hash操作

redis中的Hash 在内存中类似于一个name对应一个dic来存储 

 hset(name, key, value)

#name对应的hash中设置一个键值对(不存在,则创建,否则,修改)
r.hset("dic_name","a1","aa")

hget(name,key)

r.hset("dic_name","a1","aa")
#在name对应的hash中根据key获取value
print(r.hget("dic_name","a1"))#输出:aa

hgetall(name)

#获取name对应hash的所有键值
print(r.hgetall("dic_name"))

hmset(name, mapping)

#在name对应的hash中批量设置键值对,mapping:字典
dic={"a1":"aa","b1":"bb"}
r.hmset("dic_name",dic)
print(r.hget("dic_name","b1"))#输出:bb

hmget(name, keys, *args)

# 在name对应的hash中获取多个key的值
li=["a1","b1"]
print(r.hmget("dic_name",li))
print(r.hmget("dic_name","a1","b1"))

hlen(name)、hkeys(name)、hvals(name)

复制代码
dic={"a1":"aa","b1":"bb"}
r.hmset("dic_name",dic)

#hlen(name) 获取hash中键值对的个数
print(r.hlen("dic_name"))

#hkeys(name) 获取hash中所有的key的值
print(r.hkeys("dic_name"))

#hvals(name) 获取hash中所有的value的值
print(r.hvals("dic_name"))
复制代码

hexists(name, key)

#检查name对应的hash是否存在当前传入的key
print(r.hexists("dic_name","a1"))#输出:True

hdel(name,*keys)

#删除指定name对应的key所在的键值对
r.hdel("dic_name","a1")

hincrby(name, key, amount=1)

#自增hash中key对应的值,不存在则创建key=amount(amount为整数)
print(r.hincrby("demo","a",amount=2))

hincrbyfloat(name, key, amount=1.0)

#自增hash中key对应的值,不存在则创建key=amount(amount为浮点数)

2.1.9 发布订阅

发布者:服务器

订阅者:Dashboad和数据处理

订阅者:

复制代码
import redis

r = redis.Redis()
pub = r.pubsub()  # 生成订阅对象
pub.subscribe('fm104.5')  # 订阅哪个键,只是一个字符串
pub.parse_response()  # 解析数据结果

while True:
    print('working...')
    msg = pub.parse_response()
    print(msg)
复制代码

发布者:

import redis

r = redis.Redis()
while True:
    msg = input('>>>')
    r.publish('fm104.5', msg)  # 发布订阅

 2.1.10 sentinel模式使用

redis中的sentinel主要用于在redis主从复制中,如果master挂掉,则自动将slave替换成master

复制代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
from redis.sentinel import Sentinel
 
#  连接哨兵服务器(主机名也可以用域名)
sentinel = Sentinel([('192.168.102.101', 26379),
                     ('192.268.102.102', 26380),
                     ],
                    socket_timeout=0.5)
 
#  获取主服务器地址
master = sentinel.discover_master('mymaster')
print(master)

#  获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)

#  获取主服务器进行写入
master = sentinel.master_for('mymaster')
#master.set('foo', 'bar')
 
 
#  获取从服务器进行读取(默认是round-roubin)
slave = sentinel.slave_for('mymaster', password='redis_auth_pass')
ret = slave.get('foo')
print(ret)
复制代码

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约