복붙노트

[MONGODB] MongoDB를 / NoSQL에가 : 문서 변경 내역을 유지

MONGODB

MongoDB를 / NoSQL에가 : 문서 변경 내역을 유지

데이터베이스 응용 프로그램에 매우 일반적인 요구 사항은 데이터베이스에 하나 이상의 특정 개체에 대한 변경 사항을 추적하는 것입니다. 나는이라는 행 버전, 로그 테이블이나 역사 테이블 (나는 확실히 그것을 다른 이름이 있습니다 해요) 들었습니다. RDBMS와에 접근하는 방법에는 여러 가지가 있습니다 - 당신은 (로그의 이상) 단일 테이블에 모든 소스 테이블의 모든 변경 사항을 작성하거나 각 소스 테이블에 대해 별도의 기록 테이블을 가질 수 있습니다. 당신은 또한 응용 프로그램 코드 나 데이터베이스 트리거를 통해 로그를 관리하거나 할 수있는 옵션이 있습니다.

저도 같은 문제에 대한 해결책이없는 NoSQL / 문서 데이터베이스 (특히 MongoDB를)에서 어떻게 보이는지를 통해 생각하려고하고, 어떻게 균일 한 방법으로 해결 될 수 있어요. 이 문서의 버전 번호를 생성하고이를 덮어 결코 단순하게겠습니까? 문서는 "실제"대를위한 별도의 컬렉션을 "기록"만들기? 어떻게 이런 일이 쿼리 및 성능에 영향을 미칠까요?

어쨌든,이되는 NoSQL 데이터베이스와 일반적인 시나리오이며, 만약 그렇다면, 일반적인 솔루션은 무엇입니까?

해결법

  1. ==============================

    1.나뿐만 아니라이 나 자신을 찾고 있었다 좋은 질문입니다.

    나뿐만 아니라이 나 자신을 찾고 있었다 좋은 질문입니다.

    루비의 Mongoid 드라이버의 버전 관리 모듈을 가로 질러왔다. 내가 직접 사용하지 않은,하지만 난 찾을 수있는 것과, 각 문서에 버전 번호를 추가합니다. 이전 버전은 문서 자체에 포함됩니다. 가장 큰 단점은 전체 문서는 당신이 큰 문서를 처리 할 때 중복 콘텐츠를 많이 저장되는 결과 각 변화에 중복된다는 점이다. 이 방법은 괜찮 생각하면 작은 크기의 문서와 당신이있는 거 거래 및 / 또는 매우 자주 문서를 업데이트하지 않습니다.

    또 다른 방법은 새로운 버전에서만 변경된 필드를 저장하는 것입니다. 그럼 당신은 문서의 모든 버전을 재구성하기 위해 역사를 '평평하게'할 수 있습니다. 당신이 당신의 응용 프로그램이 최신 문서를 재구성 할 수있는 방식으로 모델 및 저장 업데이트 및 삭제의 변화를 추적 할 필요가 이것은, 다소 복잡하지만입니다. 당신이 구조화 된 문서보다는 평면 SQL 테이블을 상대하고 이것은, 까다로운 일이 될 수 있습니다.

    각 필드는 또한 개인의 역사를 가지고 있습니다. 주어진 버전으로 문서를 재구성하는 것은 훨씬 쉽게이 방법입니다. 응용 프로그램에서 명시 적으로 변경 사항을 추적해야하지만 당신은 그 값을 변경할 때 바로 재산의 새 버전을 작성하지 않습니다. 문서는 다음과 같이 보일 수 있습니다 :

    {
      _id: "4c6b9456f61f000000007ba6"
      title: [
        { version: 1, value: "Hello world" },
        { version: 6, value: "Foo" }
      ],
      body: [
        { version: 1, value: "Is this thing on?" },
        { version: 2, value: "What should I write?" },
        { version: 6, value: "This is the new body" }
      ],
      tags: [
        { version: 1, value: [ "test", "trivial" ] },
        { version: 6, value: [ "foo", "test" ] }
      ],
      comments: [
        {
          author: "joe", // Unversioned field
          body: [
            { version: 3, value: "Something cool" }
          ]
        },
        {
          author: "xxx",
          body: [
            { version: 4, value: "Spam" },
            { version: 5, deleted: true }
          ]
        },
        {
          author: "jim",
          body: [
            { version: 7, value: "Not bad" },
            { version: 8, value: "Not bad at all" }
          ]
        }
      ]
    }
    

    버전에서 삭제 된 문서의 일부를 표시하면 여전히하지만 다소 어색하다. 당신은 삭제 / 응용 프로그램에서 복원 할 수있는 부분에 대한 상태 필드가 들어갈 수 있습니다 :

    {
      author: "xxx",
      body: [
        { version: 4, value: "Spam" }
      ],
      state: [
        { version: 4, deleted: false },
        { version: 5, deleted: true }
      ]
    }
    

    이들 각각은 최신을 저장하고 하나 개의 수집 및 별도의 컬렉션의 이력 데이터 버전을 평평하게 할 수 있습니다 접근으로. 당신은 단지 문서의 최신 버전에 관심이 있다면이 번 쿼리를 개선해야한다. 최신 버전 및 히스토리 데이터 모두를 필요로 할 때, 당신은 오히려 하나보다, 두 개의 쿼리를 수행해야합니다. 응용 프로그램이 역사적 버전을 필요로하는 빈도에 의존해야 두 개의 컬렉션을 대 하나의 컬렉션을 사용의 선택에 따라서.

    이 답변의 대부분은 내 생각의 단지 뇌 덤프, 나는 실제로 아직이 중 하나를 시도하지 않았습니다. 중복 데이터의 오버 헤드 응용 프로그램에 매우 중요하지 않는 한 다시 보면, 첫 번째 옵션은 아마도 가장 쉽고 가장 좋은 솔루션입니다. 두 번째 옵션은 매우 복잡하고 아마 노력이 가치가 없습니다. 세 번째 옵션은 기본적으로 두 번째 옵션의 최적화하고 구현하기 쉽게해야하지만, 당신이 정말로 옵션 하나를 갈 수 없다면 아마 구현 노력을 가치가되지 않습니다.

    이에 대한 피드백을 기대하고, 문제에 대한 다른 사람의 솔루션 :

  2. ==============================

    2.우리는 부분적으로 우리의 사이트에 구현하고 우리는 별도의 문서 "(및 별도의 데이터베이스)에서 '스토어 개정을 사용합니다. 우리는 차이점을 반환하는 사용자 정의 함수를 작성하고 우리는 그것을 저장합니다. 열심히하지 및 자동 복구 할 수 있습니다.

    우리는 부분적으로 우리의 사이트에 구현하고 우리는 별도의 문서 "(및 별도의 데이터베이스)에서 '스토어 개정을 사용합니다. 우리는 차이점을 반환하는 사용자 정의 함수를 작성하고 우리는 그것을 저장합니다. 열심히하지 및 자동 복구 할 수 있습니다.

  3. ==============================

    3.왜 스토어에 변화는 문서 내에서 변경?

    왜 스토어에 변화는 문서 내에서 변경?

    대신 각 키 쌍에 대해 버전을 저장하는 문서에 현재 키 쌍은 항상 가장 최근의 상태와 변화의 '로그'역사를 배열 내에 저장되어 나타냅니다. 만 생성 이후 변경된 그 키는 로그에 항목이있을 것이다.

    {
      _id: "4c6b9456f61f000000007ba6"
      title: "Bar",
      body: "Is this thing on?",
      tags: [ "test", "trivial" ],
      comments: [
        { key: 1, author: "joe", body: "Something cool" },
        { key: 2, author: "xxx", body: "Spam", deleted: true },
        { key: 3, author: "jim", body: "Not bad at all" }
      ],
      history: [
        { 
          who: "joe",
          when: 20160101,
          what: { title: "Foo", body: "What should I write?" }
        },
        { 
          who: "jim",
          when: 20160105,
          what: { tags: ["test", "test2"], comments: { key: 3, body: "Not baaad at all" }
        }
      ]
    }
    
  4. ==============================

    4.하나는 현재없는 NoSQL 데이터베이스와 역사적되는 NoSQL 데이터베이스를 가질 수 있습니다. 야간 ETL에 달렸다 매일있을 것입니다. 이 ETL은 타임 스탬프 모든 값을 기록, 그래서 대신 값은 항상 튜플 (버전 필드)입니다. 그 과정에서 공간을 절약 현재 값을 만든 변화가 있었다 경우에만 새 값을 기록합니다. 예를 들어,이 기록되는 NoSQL 데이터베이스 JSON 파일과 같이 볼 수있다 :

    하나는 현재없는 NoSQL 데이터베이스와 역사적되는 NoSQL 데이터베이스를 가질 수 있습니다. 야간 ETL에 달렸다 매일있을 것입니다. 이 ETL은 타임 스탬프 모든 값을 기록, 그래서 대신 값은 항상 튜플 (버전 필드)입니다. 그 과정에서 공간을 절약 현재 값을 만든 변화가 있었다 경우에만 새 값을 기록합니다. 예를 들어,이 기록되는 NoSQL 데이터베이스 JSON 파일과 같이 볼 수있다 :

    {
      _id: "4c6b9456f61f000000007ba6"
      title: [
        { date: 20160101, value: "Hello world" },
        { date: 20160202, value: "Foo" }
      ],
      body: [
        { date: 20160101, value: "Is this thing on?" },
        { date: 20160102, value: "What should I write?" },
        { date: 20160202, value: "This is the new body" }
      ],
      tags: [
        { date: 20160101, value: [ "test", "trivial" ] },
        { date: 20160102, value: [ "foo", "test" ] }
      ],
      comments: [
        {
          author: "joe", // Unversioned field
          body: [
            { date: 20160301, value: "Something cool" }
          ]
        },
        {
          author: "xxx",
          body: [
            { date: 20160101, value: "Spam" },
            { date: 20160102, deleted: true }
          ]
        },
        {
          author: "jim",
          body: [
            { date: 20160101, value: "Not bad" },
            { date: 20160102, value: "Not bad at all" }
          ]
        }
      ]
    }
    
  5. ==============================

    5.파이썬의 사용자 (물론 최대 파이썬 3 이상)의 경우, pymongo의 컬렉션 객체의 확장이다 HistoricalCollection이 있습니다.

    파이썬의 사용자 (물론 최대 파이썬 3 이상)의 경우, pymongo의 컬렉션 객체의 확장이다 HistoricalCollection이 있습니다.

    워드 프로세서에서 예 :

    from historical_collection.historical import HistoricalCollection
    from pymongo import MongoClient
    class Users(HistoricalCollection):
        PK_FIELDS = ['username', ]  # <<= This is the only requirement
    
    # ...
    
    users = Users(database=db)
    
    users.patch_one({"username": "darth_later", "email": "darthlater@example.com"})
    users.patch_one({"username": "darth_later", "email": "darthlater@example.com", "laser_sword_color": "red"})
    
    list(users.revisions({"username": "darth_later"}))
    
    # [{'_id': ObjectId('5d98c3385d8edadaf0bb845b'),
    #   'username': 'darth_later',
    #   'email': 'darthlater@example.com',
    #   '_revision_metadata': None},
    #  {'_id': ObjectId('5d98c3385d8edadaf0bb845b'),
    #   'username': 'darth_later',
    #   'email': 'darthlater@example.com',
    #   '_revision_metadata': None,
    #   'laser_sword_color': 'red'}]
    

    전체 공개, 내가 패키지 저자. :)

  6. from https://stackoverflow.com/questions/3507624/mongodb-nosql-keeping-document-change-history by cc-by-sa and MIT license