মঙ্গোডিবি / নোএসকিউএল: নথি পরিবর্তনের ইতিহাস রাখে


134

ডাটাবেস অ্যাপ্লিকেশনগুলিতে মোটামুটি সাধারণ প্রয়োজন হ'ল ডেটাবেজে এক বা একাধিক নির্দিষ্ট সত্তায় পরিবর্তনগুলি ট্র্যাক করা। আমি এই নামক সারির সংস্করণ, একটি লগ টেবিল বা ইতিহাসের সারণী শুনেছি (আমি নিশ্চিত এটির অন্যান্য নাম আছে)। আরডিবিএমএসে এটির কাছে যাওয়ার অনেকগুলি উপায় রয়েছে - আপনি সমস্ত উত্স টেবিল থেকে একটি একক সারণীতে (লগের আরও বেশি) সমস্ত পরিবর্তন লিখতে পারেন বা প্রতিটি উত্স সারণীর জন্য পৃথক ইতিহাস সারণী রাখতে পারেন। আপনার কাছে হয় অ্যাপ্লিকেশন কোডে অথবা ডেটাবেস ট্রিগারগুলির মাধ্যমে লগইন পরিচালনা করার বিকল্প রয়েছে।

আমি কোনও নুএসকিউএল / ডকুমেন্ট ডাটাবেসে (বিশেষত মঙ্গোডিবি) একই সমস্যাটির সমাধান দেখতে কেমন হবে এবং কীভাবে এটি অভিন্ন পদ্ধতিতে সমাধান করা হবে তার মাধ্যমে আমি চেষ্টা করার চেষ্টা করছি। এটি কি নথির জন্য সংস্করণ সংখ্যা তৈরি করার মতো, এবং সেগুলি কখনই ওভাররাইটিংয়ের মতো সহজ হবে? "বাস্তব" বনাম "লগড" নথিগুলির জন্য পৃথক সংগ্রহ তৈরি করছেন? কীভাবে এটি অনুসন্ধান এবং কার্য সম্পাদনকে প্রভাবিত করবে?

যাইহোক, এটি কি নোএসকিউএল ডেটাবেসগুলির সাথে একটি সাধারণ দৃশ্য এবং যদি তাই হয় তবে একটি সাধারণ সমাধান আছে কি?


আপনি কোন ভাষা ড্রাইভার ব্যবহার করছেন?
জোশুয়া পার্টোগি

এখনও সিদ্ধান্ত নেওয়া হয়নি - এখনও ঝিম ঝিমঝিম এবং এখনও পিছনের শেষের পছন্দটি চূড়ান্ত করেনি (যদিও মঙ্গোডিবি চরম সম্ভাবনা দেখায় )। আমি নোআরএম (সি #) এর সাথে টিঙ্কারিং করছি, এবং আমি এই প্রকল্পের সাথে যুক্ত কিছু নাম পছন্দ করি, তাই এটি পছন্দ হওয়ার খুব সম্ভবত বলে মনে হয়।
ফিল স্যান্ডলার 13

2
আমি জানি এটি একটি পুরানো প্রশ্ন তবে যে কেউ মঙ্গোডিবি-র সাথে সংস্করণ খুঁজছেন, এই এসও প্রশ্নটি সম্পর্কিত এবং আরও ভাল উত্তর সহ আমার মতামত।
এওল্ফ 18'50

উত্তর:


107

ভাল প্রশ্ন, আমি নিজেও এটিকে দেখছিলাম।

প্রতিটি পরিবর্তনের উপর একটি নতুন সংস্করণ তৈরি করুন

আমি রুবির জন্য মংগয়েড ড্রাইভারের সংস্করণ মডিউলটি পেরিয়ে এসেছি । আমি নিজে এটি ব্যবহার করি নি, তবে যা খুজে পেয়েছি তা থেকে এটি প্রতিটি নথিতে একটি সংস্করণ নম্বর যুক্ত করে। পুরানো সংস্করণগুলি নথিতেই এম্বেড করা আছে। প্রধান ত্রুটিটি হ'ল প্রতিটি নথির পুরো দস্তাবেজটি সদৃশ হয়ে যায় , যার ফলে আপনি যখন বড় দস্তাবেজগুলির সাথে লেনদেন করেন তখন প্রচুর নকল সামগ্রী সংরক্ষণ করা হয়। আপনি যখন ছোট আকারের নথিগুলি নিয়ে কাজ করছেন এবং / বা খুব ঘন ঘন দস্তাবেজগুলি আপডেট না করেন তবে এই পদ্ধতিটি ঠিক আছে।

কেবলমাত্র একটি নতুন সংস্করণে পরিবর্তনগুলি সংরক্ষণ করুন

অন্য পদ্ধতিটি হ'ল কেবলমাত্র পরিবর্তিত ক্ষেত্রগুলি একটি নতুন সংস্করণে সংরক্ষণ করা । তারপরে আপনি নথির যে কোনও সংস্করণ পুনর্গঠন করতে আপনার ইতিহাসকে 'সমতল' করতে পারেন। এটি বরং জটিল, কারণ আপনার মডেলটিতে পরিবর্তনগুলি ট্র্যাক করতে হবে এবং আপডেটগুলি এবং মুছতে হবে এমন উপায়ে যাতে আপনার অ্যাপ্লিকেশনটি আপ টু ডেট ডকুমেন্টটিকে পুনর্গঠন করতে পারে। এটি জটিল হতে পারে, কারণ আপনি ফ্ল্যাট এসকিউএল টেবিলের চেয়ে কাঠামোগত দস্তাবেজগুলির সাথে কাজ করছেন।

দস্তাবেজের মধ্যে পরিবর্তনগুলি সঞ্চয় করুন

প্রতিটি ক্ষেত্রে একটি পৃথক ইতিহাস থাকতে পারে। প্রদত্ত সংস্করণে দস্তাবেজগুলি পুনর্গঠন করা এইভাবে অনেক সহজ। আপনার আবেদনে আপনাকে স্পষ্টভাবে পরিবর্তনগুলি ট্র্যাক করতে হবে না, তবে আপনি যখন তার মান পরিবর্তন করবেন তখন কেবলমাত্র একটি নতুন সংস্করণ তৈরি করুন। একটি দস্তাবেজ এর মতো দেখতে পারে:

{
  _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" }
      ]
    }
  ]
}

কোনও সংস্করণে মুছে ফেলা হিসাবে দস্তাবেজের অংশ চিহ্নিত করা এখনও কিছুটা বিশ্রী হলেও। আপনি এমন stateঅংশগুলির জন্য এমন একটি ক্ষেত্র প্রবর্তন করতে পারেন যা আপনার অ্যাপ্লিকেশন থেকে মোছা / পুনরুদ্ধার করা যায়:

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

এই প্রতিটি পদ্ধতির সাথে আপনি একটি সংকলনে একটি আধুনিক ও সমতল সংস্করণ এবং ইতিহাসের ডেটা পৃথক সংগ্রহে সংরক্ষণ করতে পারেন। যদি আপনি কেবল কোনও নথির সর্বশেষ সংস্করণে আগ্রহী হন তবে এটি ক্যোয়ারির সময়গুলি উন্নত করা উচিত। তবে যখন আপনার সর্বশেষতম সংস্করণ এবং historicalতিহাসিক ডেটা উভয়ের প্রয়োজন হবে, আপনার একটির পরিবর্তে দুটি ক্যোয়ারী করা উচিত। বনাম দুটি পৃথক সংগ্রহের একটি একক সংগ্রহে ব্যবহার নির্ভর করবে পছন্দমত তাই কত ঘন ঘন আপনার আবেদন ঐতিহাসিক সংস্করণ প্রয়োজন

এই উত্তরটির বেশিরভাগটি আমার চিন্তার একমাত্র মস্তিষ্কের ডাম্প, আমি আসলে এখনও এর কোনও চেষ্টা করি নি। এটির দিকে ফিরে তাকালে, প্রথম বিকল্পটি সম্ভবত সবচেয়ে সহজ এবং সর্বোত্তম সমাধান, যদি না ডুপ্লিকেট ডেটার ওভারহেড আপনার অ্যাপ্লিকেশনটির জন্য খুব তাৎপর্যপূর্ণ হয়। দ্বিতীয় বিকল্পটি বেশ জটিল এবং সম্ভবত চেষ্টা করার উপযুক্ত নয়। তৃতীয় বিকল্পটি মূলত বিকল্প দুটিটির একটি অপ্টিমাইজেশন এবং এটি কার্যকর করা সহজ হওয়া উচিত, তবে আপনি যদি সত্যিই অপশনটির সাথে না যেতে পারেন তবে সম্ভবত প্রয়োগের প্রচেষ্টাটি মূল্যবান নয়।

এই বিষয়ে প্রতিক্রিয়া এবং অন্যান্য লোকের সমস্যার সমাধানের জন্য অপেক্ষা করছি :)


কোথাও ডেল্টা সংরক্ষণ করার বিষয়ে কীভাবে আপনাকে flatতিহাসিক দলিল পেতে চ্যাপ্টা করতে হবে এবং সর্বদা বর্তমান পাওয়া যায়?
jpmc26

@ jpmc26 এটি দ্বিতীয় পদ্ধতির মতো, তবে সর্বশেষতম সংস্করণগুলি পেতে ডেল্টা সংরক্ষণ করার পরিবর্তে আপনি tতিহাসিক সংস্করণগুলি পেতে ডেল্টা সংরক্ষণ করছেন। কোন পদ্ধতির ব্যবহার করবেন তা নির্ভর করে আপনি কতবার historicalতিহাসিক সংস্করণগুলির প্রয়োজন need
নিলস ভ্যান ডের রেস্ট রেস্ট

আপনি দস্তাবেজটিকে বর্তমান পরিস্থিতি হিসাবে দর্শন হিসাবে ব্যবহার করার এবং দ্বিতীয় দস্তাবেজটিকে চেঞ্জলগ হিসাবে রাখার বিষয়ে একটি অনুচ্ছেদ যুক্ত করতে পারেন যা প্রতিটি পরিবর্তনকে একটি টাইমস্ট্যাম্প সহ অন্তর্ভুক্ত করবে (প্রাথমিক মানগুলি এই লগটিতে প্রদর্শিত হওয়া প্রয়োজন) - আপনি তারপরে পুনরায় খেলতে পারেন 'সময় প্রদত্ত যে কোনও বিন্দুতে এবং যেমন আপনার অ্যালগরিদম এটিটি স্পর্শ করেছিল তখন কী চলছে তা সম্পর্কিত করুন বা দেখুন যখন কোনও আইটেম এটিতে প্রদর্শিত হবে তখন ব্যবহারকারী এটিতে ক্লিক করবে।
ম্যানুয়েল আর্কড স্মিট

যদি সূচিযুক্ত ক্ষেত্রগুলি অ্যারে হিসাবে উপস্থাপিত হয় তবে এটি কি কার্য সম্পাদনকে প্রভাবিত করবে?
দিমিত্রিড

@ সমস্ত - আপনি এটি অর্জন করতে দয়া করে কিছু কোড ভাগ করে নিতে পারেন?
Pra_A

8

আমরা এটি আমাদের সাইটে আংশিকভাবে প্রয়োগ করেছি এবং আমরা 'একটি পৃথক নথিতে স্টোর রিভিশনস' ব্যবহার করি (এবং পৃথক ডাটাবেস) difআমরা ফিরিয়ে দেওয়ার জন্য আমরা একটি কাস্টম ফাংশন লিখেছিলাম এবং এটি সংরক্ষণ করি so এত কঠিন নয় এবং স্বয়ংক্রিয় পুনরুদ্ধারের জন্য অনুমতি দিতে পারি।


2
আপনি কি দয়া করে একই কাছাকাছি কিছু কোড শেয়ার করতে পারেন? এই পদ্ধতির প্রতিশ্রুতিবদ্ধ চেহারা
Pra_A

1
@ সিমিলিফেস - স্প্রিং বুট জ্যাভার্স ইন্টিগ্রেশন এটি অর্জনের পক্ষে সেরা
প্র_এ

@ পিএএ - আমি একটি প্রশ্ন জিজ্ঞাসা করেছি (প্রায় একই ধারণা)। stackoverflow.com/questions/56683389/… এর জন্য আপনার কি কোনও ইনপুট রয়েছে?
স্মাইলফ্লেস

6

দস্তাবেজের মধ্যে কেন স্টোরের কোনও পরিবর্তন হয় না ?

প্রতিটি কী জুটির বিপরীতে সংস্করণগুলি সংরক্ষণ করার পরিবর্তে ডকুমেন্টের বর্তমান কী জুটি সর্বদা সাম্প্রতিক অবস্থার প্রতিনিধিত্ব করে এবং পরিবর্তনের একটি 'লগ' ইতিহাসের অ্যারেতে সংরক্ষণ করা হয়। কেবলমাত্র সেই চাবিগুলি যা তৈরির পরে পরিবর্তিত হয়েছে লগতে প্রবেশ করবে entry

{
  _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" }
    }
  ]
}

2

একজনের কাছে বর্তমান নোএসকিউএল ডাটাবেস এবং একটি historicalতিহাসিক নোএসকিউএল ডাটাবেস থাকতে পারে। একটি রাত্রে ইটিএল প্রতিদিন চলবে। এই ইটিএল প্রতিটি মানকে একটি টাইমস্ট্যাম্পের সাথে রেকর্ড করবে, সুতরাং মানগুলির পরিবর্তে এটি সর্বদা টিপলস (সংস্করণযুক্ত ক্ষেত্র) হবে। প্রক্রিয়াতে স্থান সাশ্রয় করে বর্তমান মানটিতে কোনও পরিবর্তন ঘটে থাকলে এটি কেবলমাত্র একটি নতুন মান রেকর্ড করবে। উদাহরণস্বরূপ, এই historicalতিহাসিক নোএসকিউএল ডাটাবেস জসন ফাইলটি এর মতো দেখতে পারে:

{
  _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" }
      ]
    }
  ]
}

0

পাইথনের ব্যবহারকারীরা (পাইথন 3+ এবং অবশ্যই) এর জন্য হিস্টোরিকাল কালেকশন রয়েছে যা পাইমঙ্গোর সংগ্রহ অবজেক্টের বর্ধিত।

দস্তাবেজ থেকে উদাহরণ:

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'}]

সম্পূর্ণ প্রকাশ, আমি প্যাকেজ লেখক। :)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.