PyMongo造轮子

PyMongo造轮子

因新接手项目主使用Mongo,所以这次造轮子的主要目的是为了在接手项目中方便使用,次要目标是熟悉Pymongo

Mongo
Mongo的配置文件
初始化方法
mongo的配置
代码段
参数以及场景解析
delete_item方法
代码段
参数解析
测试代码及结果
insert_item方法
代码段
参数解析
测试代码及结果
find_item方法
代码段
参数解析
测试代码及结果
update_item方法
代码段
参数解析
测试代码及结果

下面 代码解析。

mongo配置:

from pymongo import MongoClient
from public_tools import public_settings

mongo_info = {
    'host': public_settings.MONGO_HOST
    'port': public_settings.MONGO_PORT,
    'username': public_settings.MONGO_USERNAME,
    'password': public_settings.MONGO_PASSWORD,
}
public_tools 为自定义的公共配置方法
参照: 我使用的是局域网ip(具体配置更换自己的😊)
MONGO_HOST = '191.168.1.1'
MONGO_PORT = 27017
MONGO_USERNAME = 'username'
MONGO_PASSWORD = 'password'

初始化方法:

    def __init__(self, db, table, many=True, client_close=False):
        '''
        初始化方法做了自动连接,创建游标
        默认操作完成后,自动关闭连接
        如需要手动关闭的情况,修改client_close,会返还连接对象
        :param db: 哪个库
        :param table: 哪张表
        :param many: 操作单条还是多条数据 默认为全部
        :param client_close: 是否自动关闭连接 默认为自动关闭
        '''
        self.uri = 'mongodb://{}:{}@{}:{}'.format(
        	mongo_info['username'], mongo_info['password'],
        	mongo_info['host'], mongo_info['port'])
        self.client = MongoClient(self.uri)
        db = self.client[db]
        self.cursor = db[table]
        self.many = many
        self.client_close = client_close
因业务需求,所以我在初始化方法中直接链接mongo,创建了游标,何时释放连接由
client_close参数控制。当时加这个参的原因是出于遍历操作的场景
如:
    for filter in filter_list:
        client,results = cursor.find(filter)
    client.close()
该情况下就需要返回链接,在循环外关闭了。
正常场景,使用默认的client_close,各操作方法内会自动关闭连接

many参数是为了控制是处理第一条符合filter条件的数据还是多条的,后续会讲

delete_item方法:

    def delete_item(self, filter):
        """
        删
        :param filter: 筛选条件
        :return:
        """
        if type(filter) == dict:
            if self.many:
                result_data = self.cursor.delete_many(filter=filter)
                result = 'delete success, delete_count: {}'.format(result_data.deleted_count)
            else:
                result_data = self.cursor.delete_one(filter=filter)
                result = 'delete success, delete_count: {}'.format(result_data.deleted_count)
        else:
            result = 'filter type error...only dict'

        if self.client_close == 'off':
            self.client.close()
            print('auto close client')
            return result
        else:
            return self.client, result

为什么不按照增删改查的顺序来呢?是因为删的逻辑最简单 😄

delete方法外层先判断filter参数是否合规,必须为dict 例如{'age': '18'}
if type(filter) == dict:
	pass
else:
	result = 'filter type error'

many参数判断是操作符合条件的第一条还是全部数据,默认为全部
因为业务逻辑大部分处理的是符合条件的全部数据,所以就省事定义了默认值,写到了初始化方法中。见谅~
if self.many:
    result_data = self.cursor.delete_many(filter=filter)
    result = 'delete success, delete_count: {}'.format(result_data.deleted_count)
else:
    result_data = self.cursor.delete_one(filter=filter)
    result = 'delete success, delete_count:{}'.format(result_data.deleted_count)
然后通过delete_many方法或delete_one方法去执行操作
返回的result_data为一个对象,具体的参数可以调试查看哦 
我使用了其中比较重要的deleted_count参数,返回删除成功的数据条数

client_close参数判断是需要方法内关闭,还是返回连接方法外关闭。
默认为方法内关闭连接。也是为了省事,再次见谅~
if self.client_close == False:
   self.client.close()
   print('auto close client')
   return result
else:
   return self.client, result

delete测试代码

# --------- delete_item test code ---------
MongoTool()为类方法的名字
# 第一种 删除符合filter规则的所有数据/自动关闭连接  
结果: 成功删除/自动关闭连接
cursor = MongoTool(db=db, table=table)
results = cursor.delete_item(filter={'age': '18'})
# 第二种 删除符合filter规则的第一条数据/自动关闭连接 
结果: 成功删除/自动关闭连接
cursor = MongoTool(db=db, table=table, many=False)
results = cursor.delete_item(filter={'age': '18'})
# 第三种 for循环删除符合filter规则的所有数据/手动关闭连接 
结果: 成功删除/手动关闭连接
cursor = MongoTool(db=db, table=table, client_close=True)
filter_list = [{'age': '18'}, {'sex': 'boy'}]
for filter in filter_list:
    client, results = cursor.delete_item(filter=dict(filter))
    print(results)
client.close()

insert_item方法:

    def insert_item(self, data):
        """
        增 根据data类型判断时单条插入还是多条插入
        插入数据操作
        :param sql:
        :return:
        """
        if type(data) == dict:
            try:
                result_data = self.cursor.insert_one(data)
                result = 'success..insert_id: {}'.format(result_data.inserted_id)
            except Exception as e:
                result = 'insert data error! \nErrorReason: [ {} ]'.format(e)
        elif type(data) == list:
            try:
                result_data = self.cursor.insert_many(data)
                result = 'success..insert_id_list: {}'.format(result_data.inserted_ids)
            except Exception as e:
                result = 'insert data error! \nErrorReason: [ {} ]'.format(e)
        else:
            result = 'insert_data type error'

        if self.client_close == False:
            self.client.close()
            print('auto close client')
            return result
        else:
            return self.client, result
insert方法判断了插入的data类型
如: 
	data = {'age': 13}
	data1 = [{'age': 13}, {'age': 14}]
当data为dict时,判断为插入单条数据,执行insert_one()方法
当data为list时,判断为插入多条数据,执行insert_many()方法
插入成功的result主要打印了插入的inserted_id/inserted_ids
依然是根据初始化方法的client_close参数来判断是否需要在方法外关闭连接

insert测试代码

data = {'age': 13}
data1 = [{'age': 13}, {'age': 14}]
# 根据data类型判断 dict的为插入单条,list为插入多条
# 第一种 插入符合规则的一条数据/自动关闭连接
结果 # _id = 6079475810747234d503b02e 插入成功/自动关闭连接
cursor = MongoTool(db=db, table=table)
result = cursor.insert_item(data=data) 

# 第二种 插入符合规则的多条数据/自动关闭连接
结果 # _ids = [ObjectId('607947dafa468affe394b555'), ObjectId('607947dafa468affe394b556')] 插入成功/自动关闭连接
cursor = MongoTool(db=db, table=table)
result = cursor.insert_item(data=data1)

# 第三种 循环插入数据/做手动关闭连接
结果 
# 1-success..insert_id: 60794872d430bc78ada7e1b6 数据插入成功,
# 2-success..insert_id: 60794872d430bc78ada7e1b7 数据插入成功,
连接手动关闭成功 
cursor = MongoTool(db=db, table=table, client_close='on')
for data in data1:
    client, result = cursor.insert_item(data=data)
    print(result)  
client.close()     

find_item方法:

    def find_item(self, filter, limit_num=None, skip_num=None):
       '''
       对返回值做统一处理 空值为: [], 单条的为: [dict], 多条的没[dict1, dict2]
       :param filter: 查询条件 {'字段': '值'} 默认不做分页
       :param limit_num: 分页 没有skip的话,取0-limit_num条数据
       :param skip_num: 起始页 有skip的话,取skip_num至skip_num+limit_num的数据 是一个区间
       :return: result 为查询结果的列表,为空时代表没有符合条件的数据集
       '''
       if type(filter) == dict:
           if self.many:
               if limit_num:
                   if skip_num:
                       print('[get {}- {} data]'.format(skip_num, skip_num + limit_num))
                       result = list(self.cursor.find(filter).skip(skip_num).limit(limit_num))
                   else:
                       print('[get Top {} data]'.format(limit_num))
                       result = list(self.cursor.find(filter).limit(limit_num))
               else:
                   print("not limit")
                   result = list(self.cursor.find(filter))
           else:
               result_dict = self.cursor.find_one(filter)
               result = []
               result.append(result_dict)
       else:
       	   result = 'fitter type error'
           

       if self.client_close == 'off':
           print('auto close client start')
           self.client.close()
           print('auto close client end')
           return result
       else:
           return self.client, result
find_item多了俩个参数
分页 limit_num=None 有limt_num,没有skip的话,取0-limit_num条数据
起始页 skip_num=None 有skip的话,取skip_num至skip_num+limit_num的数据
方法第一层 
	if type(filter) == dict:
	判断筛选条件是否为dict 不为dict的话,result=‘error info’
方法第二层
	if self.many:
	判断依然是判断操作单条还是多条数据,默认是符合filter条件的全部数据
	many=True 执行find()方法 
	limit_num skip_num这俩个参数没有传值时,
		result = list(self.cursor.find(filter)) #取出符合条件的所有数据
	limit_num有传值, skip_num没有的话,
		result = list(self.cursor.find(filter).limit(limit_num)) 
	limit_num和skip_num都有传值的话,
		result = list(self.cursor.find(filter).skip(skip_num).limit(limit_num))
	many=False 执行find_one()方法 因为find_one返回值为dict 为了统一返回值,将dict添加至列表,返回列表

依然是根据初始化方法的client_close参数来判断是否需要在方法外关闭连接	
    if self.client_close == 'off':
        print('auto close client start')
        self.client.close()
        print('auto close client end')
        return result
    else:
        return self.client, result
# ---------- find_item test code ----------
# 第一种 查询符合规则的所有数据/未做分页/自动关闭连接 共98条数据 auto close client 查询成功/自动关闭连接
cursor = MongoTool(db=db, table=table)
results = cursor.find_item(filter={'regionName': '北京'})
# 第二种 查询符合规则的所有数据/做分页/自动关闭连接 limit_num=30 前30条数据 查询成功/自动关闭连接
cursor = MongoTool(db=db, table=table)
results = cursor.find_item(filter={'regionName': '北京'}, limit_num=30)
# 第三种 查询符合规则的所有数据/做分页/固定值开始/自动关闭连接 limit_num=30, skip_num=20 第(20条)至第(20+30条)数据 查询成功/自动关闭连接
cursor = MongoTool(db=db, table=table)
results = cursor.find_item(filter={'regionName': '北京'}, limit_num=30, skip_num=20)
# 第四种 查询符合规则的第一条数据/自动关闭连接 查询成功/自动关闭连接
cursor = MongoTool(db=db, table=table, many=False)
results = cursor.find_item(filter={'regionName': '北京'})
# 第五种 for循环取符合规则的所有获取数据/手动关闭连接/未做分页 查询成功/手动关闭连接成功
cursor = MongoTool(db=db, table=table, client_close='on')
filter_list = [{'regionName': '北京'}, {'regionName': '江苏'}]
for filter in filter_list:
    client, results = cursor.find_item(filter=filter)
client.close()
print('client close')

update_item方法:

    def update_item(self, filter, data, upsert=True, multi=False):
       """
       :param fifter: 筛选条件
       :param data: 更新数据
       :param upsert: True: 存在更新 不存在插入 False: 不做插入,跳过
       :param multi: True: 符合筛选条件,全部做更新 False: 只更新找到的第一条记录
       :return:
       """
       if type(filter) and type(data) == dict:
           result_data = self.cursor.update(filter, {'$set': data}, upsert=upsert, multi=multi)
           if result_data['ok'] == 1.0:
               result = 'update success... filter_num: {}, modified: {}'.format(result_data['n'],
                                                                                result_data['nModified'])
       else:
           result = 'filter or data type error...only dict'

       if self.client_close == 'off':
           self.client.close()
           print('auto close client')
           return result
       else:
           return self.client, result
更新涉及到问题
   upsert参数
       True 根据筛选条件,如果存在更新,不存在的话创建。
       (省去了先查数据库,确定是否有对应文档,再决定更新还是插入。mongo🐂🍺)
   multi参数
       True: 符合筛选条件,全部做更新 
       False: 只更新找到的第一条记录
  查询成功后,返回的result为符合条件的条数和已更新的条数

经测试一般使用没啥问题,但还是感觉有点别扭,具体的别扭可能是用习惯了PyMongo,我有感觉这次造轮子最后的结果可能是脱裤子放屁–>多次一举 了😭, 不过只好安慰自己,当学习过程了,学习下mongo的使用和封装要考虑的多重可能性 喏 奖励自己个赞~👍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值