def item_delete(self, collection: str, oid: Union[ObjectId, str], delete_key: str, query: Union[list, None]) -> bool: """ ドキュメントの項目を削除する :param str collection: :param oid: :type oid: str or ObjectId :param str delete_key: :param query: :type query: list or None :return: :rtype: bool """ oid = Utils.conv_objectid(oid) doc = self.db[collection].find_one({'_id': oid}) if doc is None: sys.exit('ドキュメントが存在しません') if query is not None: # emb try: doc = Utils.doc_traverse(doc, [delete_key], query, self._delete_execute) except Exception as e: sys.exit(e) else: # ref try: del doc[delete_key] except IndexError: sys.exit(f'キーは存在しません: {delete_key}') # ドキュメント置き換え処理 replace_result = self.db[collection].replace_one({'_id': oid}, doc) result = True if replace_result.modified_count == 1 else False return result
def delete(self, delete_oid: ObjectId, collection: str, oid: Union[ObjectId, str], structure: str, query=None) -> bool: """ 該当のoidをファイルリファレンスから削除し、GridFSからファイルを削除 :param ObjectId delete_oid: :param str collection: :param str oid: :param str structure: :param query: :type query: list or None :return: :rtype: bool """ oid = Utils.conv_objectid(oid) # ドキュメント存在確認&コレクション存在確認&対象ドキュメント取得 doc = self.db[collection].find_one({'_id': oid}) if doc is None: sys.exit('対象のコレクション、またはドキュメントが存在しません') # ファイルリスト取得 files_list = self.get_file_ref(doc, structure, query) # リファレンスデータを編集 if len(files_list) > 0: # 何らかの原因で重複があった場合を避けるため一度setにする files_list = list(set(files_list)) files_list.remove(delete_oid) else: sys.exit('ファイルが存在しません') # ドキュメントを新しいファイルリファレンスに置き換える if structure == 'ref': try: new_doc = self._file_list_replace(doc, files_list) except Exception as e: sys.exit(e) elif structure == 'emb': try: new_doc = Utils.doc_traverse(doc, files_list, query, self._file_list_replace) except Exception as e: sys.exit(e) else: sys.exit('structureはrefまたはembの指定が必要です') replace_result = self.db[collection].replace_one({'_id': oid}, new_doc) # fsから該当ファイルを削除 if replace_result.modified_count: self.fs_delete([delete_oid]) # ファイルが削除されたか検証 if self.fs.exists(delete_oid): return False else: return True
def add_file_reference(self, collection: str, oid: Union[ObjectId, str], file_path: Tuple[Path], structure: str, query=None, compress=False) -> bool: """ ドキュメントにファイルリファレンスを追加する ファイルのインサート処理、圧縮処理なども行う :param str collection: :param oid: :type oid: ObjectId or str :param tuple file_path: :param str structure: :param query: :type query: list or None :param bool compress: default False :return: :rtype: bool """ oid = Utils.conv_objectid(oid) # ドキュメント存在確認&対象ドキュメント取得 doc = self.db[collection].find_one({'_id': oid}) if doc is None: sys.exit('対象のドキュメントが存在しません') if structure == 'emb': # クエリーがドキュメントのキーとして存在するかチェック if not Utils.query_check(query, doc): sys.exit('対象のドキュメントに対してクエリーが一致しません.') # ファイルのインサート inserted_file_oids = [] for file in self.file_gen(file_path): file_obj = file[1] metadata = {'filename': file[0]} if compress: file_obj = gzip.compress(file_obj, compresslevel=6) metadata.update({'compress': 'gzip'}) inserted_file_oids.append(self.fs.put(file_obj, **metadata)) if structure == 'ref': new_doc = self._file_list_attachment(doc, inserted_file_oids) elif structure == 'emb': try: new_doc = Utils.doc_traverse(doc, inserted_file_oids, query, self._file_list_attachment) except Exception as e: sys.exit(e) else: sys.exit('構造はrefかembが必要です') # ドキュメント差し替え replace_result = self.db[collection].replace_one({'_id': oid}, new_doc) if replace_result.modified_count == 1: return True else: # 差し替えができなかった時は添付ファイルは削除 self.fs_delete(inserted_file_oids) return False
def test_doc_traverse(self): # 正常系1 対象のキーを削除する doc = { 'a': '1', 'b': [{ 'd': { 'e': '4', 'f': [ObjectId(), ObjectId(), ObjectId()], 'g': '5' } }, { 'c': '3' }] } del_keys = ['f'] query = ['b', '0', 'd'] def delete(doc, keys): for key in keys: if key in doc: del doc[key] actual = Utils.doc_traverse(doc, del_keys, query, delete) expected = {'a': '1', 'b': [{'d': {'e': '4', 'g': '5'}}, {'c': '3'}]} self.assertDictEqual(actual, expected) # 例外のテスト1 クエリのインデックスの不備 query = ['bbb', '2', 'eee', '2'] doc = { 'aaa': '123', 'bbb': [{ 'ccc': '456' }, { 'ddd': '789' }, { 'eee': [{ 'fff': { 'ans': 'OK' } }, { 'ggg': '1', 'hhh': 'iii' }] }] } oids = [ObjectId(), ObjectId(), ObjectId()] with self.assertRaises(IndexError): _ = Utils.doc_traverse(doc, oids, query, delete) # 例外のテスト2 クエリの指定ミス query = ['bbb', '2', 'eee', 'xxx'] doc = { 'aaa': '123', 'bbb': [{ 'ccc': '456' }, { 'ddd': '789' }, { 'eee': [{ 'fff': { 'ans': 'OK' } }, { 'ggg': '1', 'hhh': 'iii' }] }] } oids = [ObjectId(), ObjectId(), ObjectId()] with self.assertRaises(ValueError): _ = Utils.doc_traverse(doc, oids, query, delete)