async def save(self, session=None, **kwargs): """ 保存--如果待保存Document包含属性_id,这执行更新操作,否则执行更新操作 :param session: 会话 :return: 已保存数据主键ID """ _c = getattr(self, '__collection_name') if _c and _c == 'TBL_MEMBER': source = getattr(self, 'source') if source and isinstance(source, int): setattr(self, 'source', str(source)) logger.info( 'The source of (%s) is %s, will be change type from %s to str' % (self.__class__, source, type(source))) save_doc = self.result_2_dict() oid = save_doc.get('_id') if oid: await self.get_async_collection().update_one({'_id': oid}, {'$set': save_doc}, upsert=True, session=session, **kwargs) else: if '_id' in save_doc.keys(): del save_doc['_id'] insert_result = await self.get_async_collection().insert_one( save_doc, session=session, **kwargs) if insert_result: oid = insert_result.inserted_id # 清除缓存 if self.__cached: CacheEngine.delete(oid) return oid
def sync_get_by_cid(cls, cid, read_preference=None, session=None, **kwargs): """ 依据主键_id获取Document :param cid: 记录主键(cid) :param read_preference: :param session: :param kwargs :return: """ result, clazz = None, cls() if clazz.__cached: result = clazz.result_2_obj(CacheEngine.get(cid)) if not result and clazz: collection = clazz.get_sync_collection(read_preference) if collection: result = clazz.result_2_obj( collection.find_one(clazz.map_filter_2_field({'cid': cid}), session=session, **kwargs)) if result and clazz.__cached: CacheEngine.set(cid, result) return result
async def update_many(cls, requests, session=None, **kwargs): """ 批量更新 :param requests: 操作请求 :param session: 会话 :return: """ if not requests: raise ValueError('Lack requests, please specified.') for request in requests: if not isinstance(request, (UpdateOne, ReplaceOne)): raise TypeError( "'requests' value must be instance ReplaceOne.") clazz = cls() result = await clazz.get_async_collection().bulk_write(requests, session=session, **kwargs) if result: if clazz.__cached: obj_list = await clazz.get_async_collection().aggregate([{ '$match': { '$or': [request._filter for request in requests] } }, { '$group': { '_id': '$_id' } }]).to_list(None) CacheEngine.delete_many(list([obj.id for obj in obj_list])) return result.modified_count return 0
async def get_by_id(cls, oid, read_preference=None, session=None, **kwargs): """ 依据主键_id获取Document :param oid: 记录主键(_id) :param read_preference :param session: 会话 :return: """ if isinstance(oid, ObjectId): oid = str(oid) result, clazz = None, cls() if clazz.__cached: result = clazz.result_2_obj(CacheEngine.get(oid)) if not result and clazz: result = clazz.result_2_obj( await clazz.get_async_collection(read_preference).find_one( filter=clazz.map_filter_2_field({'_id': ObjectId(oid)}), session=session, **kwargs)) if result and clazz.__cached: CacheEngine.set(oid, result) return result
async def delete_by_ids(cls, ids, session=None, **kwargs): """ 依据ID删除记录 :param ids: ID列表 :param session: 会话 :return: """ if not isinstance(ids, (list, tuple)): raise TypeError("'ids' must be a list or tuple.") bulk_requests, tmp_id_list = [], [] for oid in ids: tmp_id_list.append(str(oid)) bulk_requests.append( DeleteOne( {'_id': ObjectId(oid) if isinstance(oid, str) else oid})) if bulk_requests: clazz = cls() result = await clazz.get_async_collection().bulk_write( bulk_requests, session=session, **kwargs) if result: # 清除缓存 if clazz.__cached: CacheEngine.delete_many(tmp_id_list) return result.deleted_count return 0
def sync_delete(self, session=None, **kwargs): """ 删除 :return: """ save_dict = self.result_2_dict() if '_id' not in save_dict.keys(): raise InvalidDocumentError('Not a valid database record.') result = self.get_sync_collection().delete_one( {'_id': ObjectId(save_dict.get('_id'))}, session=session, **kwargs) if result and result.deleted_count == 1: # 清除缓存 if self.__cached: CacheEngine.delete(getattr(self, 'oid')) return True return False
def get_async_collection(self, read_preference=None): """ 获取数据库集合对象 :return: """ db = MotorEngineDB().get_database(getattr(self, '__db_name')) # 初始化缓存 if CacheEngine.enable == 0: CacheEngine.switch_db(db) CacheEngine.initialize() # 获取连接 collection = db[getattr(self, '__collection_name')] if read_preference: collection = collection.with_options( read_preference=read_preference) setattr(collection, 'mapping_class', self.__class__) return collection
def sync_update_many(cls, requests, session=None, **kwargs): if not requests: raise ValueError('Lack requests, please specified.') for request in requests: if not isinstance(request, (UpdateOne, ReplaceOne)): raise TypeError( "'requests' value must be instance ReplaceOne.") clazz = cls() result = clazz.get_sync_collection().bulk_write(requests, session=session, **kwargs) if result: upserted_ids = result.upserted_ids if clazz.__cached: CacheEngine.delete_many( list([str(oid) for oid in upserted_ids])) return result.modified_count return 0
def sync_delete_many(cls, filtered, session=None, **kwargs) -> int: if not filtered: raise ValueError('Lack filter conditions, please specified.') clazz = cls() t_filtered = clazz.map_filter_2_field(filtered) oid_list = [] if clazz.__cached: oid_list = [ str(oid) for oid in clazz.sync_distinct('_id', t_filtered) ] result = clazz.get_sync_collection().delete_many(t_filtered, session=session, **kwargs) if result: if clazz.__cached: CacheEngine.delete_many(list(oid_list)) return result.deleted_count return 0
def sync_update_many_by_filtered(cls, filtered: dict = None, update: dict = None, force: bool = False, session=None, **kwargs): """更新多个文档 :param filtered: 筛选条件 :param update: 更新操作 $set, $unset, $rename 参考: https://docs.mongodb.com/manual/reference/operator/update/ :param force 由于filtered == {} 时,将会更新整个数据表, 属于高危操作, 因此限制只有在使用force设置时,才允许更新, 要求使用者必须清楚自己的操作 :param session: 会话 :param kwargs: 可使用的其他参数 upsert=False, array_filters=None, bypass_document_validation=False, collation=None :return: """ if not update: return 0 if filtered is {} and not force: # 尝试更新整个数据表, 确未指定强制操作时返回0 return 0 clazz = cls() filter = clazz.map_filter_2_field(filtered) update = clazz.map_filter_2_field(update) result = clazz.get_sync_collection().update_many(filter, update, session=session, **kwargs) if result: if clazz.__cached: oid_list = clazz.get_sync_collection(read_preference=ReadPreference.PRIMARY) \ .distinct('_id', filter, session) CacheEngine.delete_many(oid_list) return result.modified_count return 0
async def delete_many(cls, filtered, session=None, **kwargs) -> int: """ 删除多条记录 :param filtered: 筛选条件 :param session: 会话 :return: """ if not filtered: raise ValueError('Lack filter conditions, please specified.') clazz = cls() t_filtered = clazz.map_filter_2_field(filtered) oid_list = [] if clazz.__cached: oid_list = [ str(oid) for oid in await clazz.distinct('_id', t_filtered) ] result = await clazz.get_async_collection().delete_many( filter=t_filtered, session=session, **kwargs) if result: if clazz.__cached: CacheEngine.delete_many(list(oid_list)) return result.deleted_count return 0
def sync_save(self, session=None, **kwargs): """ 保存--如果待保存Document包含属性_id,这执行更新操作,否则执行更新操作 :return: 已保存数据主键ID """ save_doc = self.result_2_dict() oid = save_doc.get('_id') if oid: self.get_sync_collection().update_one({'_id': oid}, {'$set': save_doc}, upsert=True, session=session, **kwargs) else: if '_id' in save_doc.keys(): del save_doc['_id'] insert_result = self.get_sync_collection().insert_one( save_doc, session=session, **kwargs) if insert_result: oid = insert_result.inserted_id # 清除缓存 if self.__cached: CacheEngine.delete(oid) return oid