programing

mongodb에서 문서를 캐스케이드로 삭제하는 방법은 무엇입니까?

powerit 2023. 6. 27. 22:38
반응형

mongodb에서 문서를 캐스케이드로 삭제하는 방법은 무엇입니까?

나는 Mongodb에 사용자 문서와 사진 문서를 가지고 있습니다.각 사진은 사용자의 것이며 사진은 사용자 간에 공유될 수 있습니다.예를 들어 user1은 p1,p2,p3 사진이고 user2는 p3,p4,p5 사진입니다.제가 user1을 삭제하면(Compass와 같은 도구를 수동으로 사용하여), p1과 p2도 삭제해야 하지만 p3는 삭제하면 안 됩니다.이를 달성하는 방법과 어떤 종류의 데이터베이스 구조를 정의해야 합니까?

현재 user1을 삭제하면 사진이 삭제되지 않고 데이터베이스에 남아 데이터베이스를 사용하는 애플리케이션의 관점에서 데이터베이스가 손상됩니다.

Spring Boot 앱과 User and Photo는 다음과 같이 선언되었습니다.

import lombok.Builder;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
@Data
@Builder
public class User {

    @Id
    private String id;


    @DBRef
    private Set<Photo> photos;


    private String name;
}

@Document
@Data
@Builder
public class Photo {

    @Id
    private String id;


    private String fileName;

}

m4gic과 그가 링크한 질문(여기와 여기)에서 언급했듯이 MongoDB는 계단식 삭제를 지원하지 않습니다.이 경우에는 사용자 오브젝트에 배열을 작성한 후 전체 하위 문서를 해당 배열에 저장해야 합니다.이렇게 하면 부모의 일부이기 때문에 부모와 함께 삭제됩니다.

MongoDB는 현재 캐스케이드 삭제를 지원하지 않습니다.참조 사진을 User 모델에 이미 저장하고 있으므로 참조 목록에서 사진 ID를 가져와 함께 삭제할 수 있습니다.또는 사진을 별도의 컬렉션에 저장하는 대신 사진 배열을 사용자 개체에 포함시킬 수 있습니다.

다음 링크도 참조할 수 있습니다.N:M 관계에 대해 MongoDB에서 계단식 삭제를 권장하는 것은 무엇입니까?

@마인드크래프트가 옳지만 사진을 별도의 컬렉션에 보관하려면 액세스 속성을 추가할 수 있습니다.photo와 같은 문서

{
  ref: 'https://....',
  access:[user1._id, user2._id]
}

그런 다음 -와 같이 쿼리할 수 있습니다.

db.photos.find({access:{$in:[user1._id]}})

비록 사진을 위한 별도의 수집은 큰 도움이 되지 않을 것입니다.대신 사진 URL을 배열에 넣으십시오.

다음은 캐스케이드 삭제를 위한 일반적인 파이썬 구현입니다.'외부 키'가 부모의 ObjectId라고 가정합니다.

컨텍스트를 입력할 때 Enter 메서드를 호출하고 discover_collections 메서드를 자동으로 호출하여 ObjectId 참조가 포함된 컬렉션을 찾습니다.종료 메서드는 컨텍스트가 종료될 때 호출되며 MongoDB 클라이언트 연결을 닫습니다.

클래스를 컨텍스트 관리자로 사용하면 MongoDB 연결이 적절하게 관리되고 discover_collections 메서드가 적절한 시간에 호출됩니다.

<mongodb_connection_string>을 실제 MongoDB 연결 문자열로 바꾸고 'your_database_name'을 데이터베이스 이름으로 바꾸는 것을 잊지 마십시오.

컨텍스트 내에서 클래스 호출:

with CascadeDelete('<mongodb_connection_string>', 'your_database_name') as cascade_delete:
    cascade_delete.delete(ObjectId('parent1'))

CascadeDelete 클래스 구현:

from pymongo import MongoClient
from bson.objectid import ObjectId


class CascadeDelete:
    """ Usage:

        with CascadeDelete('<mongodb_connection_string>', 'your_database_name') as cascade_delete:
            cascade_delete.delete(ObjectId('parent1'))
    """
    def __init__(self, connection_string, database_name):
        self.client = MongoClient(connection_string)
        self.db = self.client[database_name]
        self.collections = []

    def __enter__(self):
        self.discover_collections()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.client.close()

    def discover_collections(self):
        for collection_name in self.db.list_collection_names():
            collection = self.db[collection_name]
            if self._has_objectid_references(collection):
                self.collections.append(collection)

    def delete(self, document_id):
        deleted_documents = set()
        self._delete_documents(document_id, deleted_documents)

        for collection in self.collections:
            collection.delete_many({'_id': {'$in': list(deleted_documents)}})

    def _delete_documents(self, document_id, deleted_documents):
        deleted_documents.add(document_id)

        for collection in self.collections:
            document = collection.find_one({'_id': document_id})
            if document:
                for key, value in document.items():
                    if isinstance(value, ObjectId) and key != '_id':
                        self._delete_documents(value, deleted_documents)

    @staticmethod
    def _has_objectid_references(collection):
        sample_document = collection.find_one()
        if not sample_document:
            return False

        for value in sample_document.values():
            if isinstance(value, ObjectId):
                return True

        return False

이게 누군가에게 도움이 되길...

안부의 말

언급URL : https://stackoverflow.com/questions/52148305/how-to-cascade-delete-document-in-mongodb

반응형