Ejemplo n.º 1
0
Archivo: db.py Proyecto: ryde/EDMAN
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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)