रेल एक बड़ा ढांचा है जिसमें विशिष्ट परिस्थितियों के लिए बहुत सारे आसान अंतर्निहित उपकरण हैं। इस श्रृंखला में, हम रेल के बड़े कोडबेस में छिपे कुछ कम ज्ञात टूल पर एक नज़र डालेंगे।
इस लेख में, हम ActiveRecord के store
. पर ध्यान केंद्रित करेंगे और store_accessor
तरीके। इन दोनों विधियों का उद्देश्य JSON या YAML जैसे डेटाबेस कॉलम में संरचित डेटा संग्रहीत करने के उपयोग के मामले में है। जबकि store_accessor
हमें गेटटर विधियों, store
के साथ एक मॉडल को बंद किए बिना इन डेटा से मूल्यों को हथियाने का एक आसान तरीका देता है एक कदम और आगे जाता है और हमारे चुने हुए प्रारूप में डेटा को पारदर्शी रूप से क्रमबद्ध/deserializes करता है। यह समझने के लिए कि यह कहाँ उपयोगी हो सकता है, हम JSON को रिलेशनल डेटाबेस में संग्रहीत करने के विकल्पों और कुछ कारणों पर भी एक नज़र डालेंगे जो आप ऐसा करना चाहते हैं।
डेटाबेस में JSON
मुझे स्पष्ट करना चाहिए कि जब मैं इस लेख में 'डेटाबेस' कहता हूं, तो मैं रिलेशनल डेटाबेस, विशेष रूप से पोस्टग्रेएसक्यूएल और माईएसक्यूएल का जिक्र कर रहा हूं, क्योंकि वे रेल समुदाय में सबसे व्यापक रूप से उपयोग किए जाते हैं।
कोई पूछ सकता है कि आप JSON को रिलेशनल डेटाबेस में क्यों स्टोर करना चाहेंगे। दरअसल, संबंधपरक डेटाबेस के लाभों का लाभ उठाने का तरीका डेटा को तोड़ना है ताकि रिश्ते उनके बीच डेटाबेस (जैसे, विदेशी कुंजी) द्वारा लागू किया जा सकता है, और क्वेरी प्रदर्शन को बेहतर बनाने के लिए डेटा को अनुक्रमित किया जा सकता है।
रिलेशनल डेटाबेस मॉडल का एक दोष यह है कि डेटा संरचना को समय से पहले और दोनों के बारे में पता होना चाहिए तालिका में प्रत्येक पंक्ति के लिए समान। यदि आपका एप्लिकेशन डेटा के आसपास बनाया गया है जो इन आवश्यकताओं को पूरा नहीं करता है, तो आप NoSQL डेटाबेस की जांच करना चाह सकते हैं। अधिकांश वेब ऐप्स के लिए, हालांकि, हम ~~डेविल~~ रिलेशनल डेटाबेस से चिपके रहना चाहते हैं जिसे हम अधिकांश डेटा के लिए जानते हैं और इन गतिशील डेटा संरचनाओं में विवेकपूर्ण तरीके से "छिड़काव" करते हैं। इन मामलों में, JSON कॉलम जैसा कुछ बहुत मायने रखता है।
JSON बनाम JSONB
PostgreSQL में दो प्रकार के JSON कॉलम होते हैं:json
और jsonb
. मुख्य अंतर यह है कि jsonb
राइट-टाइम पर पार्स किया जाता है, जिसका अर्थ है कि डेटा एक प्रारूप में संग्रहीत किया जाता है जिसे डेटाबेस तेजी से क्वेरी कर सकता है। चेतावनी यह है कि क्योंकि JSON पहले से ही पार्स किया गया है, जब टेक्स्ट के रूप में आउटपुट होता है, तो यह अब उपयोगकर्ता द्वारा दर्ज किए गए मेल से मेल नहीं खा सकता है। उदाहरण के लिए, डुप्लिकेट कुंजियों को हटाया जा सकता है, या कुंजी क्रम मूल से मेल नहीं खा सकता है।
पोस्टग्रेएसक्यूएल दस्तावेज कहता है कि ज्यादातर मामलों में, jsonb
जब तक आपके पास कोई विशेष कारण न हो, तब तक आप यही चाहते हैं।
MySQL का json
कॉलम jsonb
के समान व्यवहार करता है पोस्टग्रेएसक्यूएल में। 'उपयोगकर्ता ने जो दर्ज किया' आउटपुट का समर्थन करने के लिए, आपको शायद varchar
. का उपयोग करना होगा कॉलम या ऐसा ही कुछ।
JSON बनाम टेक्स्ट
डेटा को पूर्व-पार्स करने की अनुमति देने के अलावा, एक टेक्स्ट फ़ील्ड में समान डेटा संग्रहीत करने के बजाय JSON कॉलम का उपयोग करने से उन प्रश्नों की अनुमति मिलती है जो डेटा का उपयोग करते हैं। उदाहरण के लिए, आप उन सभी रिकॉर्ड्स को क्वेरी कर सकते हैं जहां कॉलम में एक विशेष की-वैल्यू पेयर मौजूद है। ध्यान दें कि रेल स्वयं कई (यदि कोई हो) JSON- विशिष्ट प्रश्नों का समर्थन नहीं करते हैं, क्योंकि वे डेटाबेस-विशिष्ट हैं। इस प्रकार, यदि आप इन सुविधाओं का लाभ उठाना चाहते हैं, तो ऐसा करने के लिए आपको SQL क्वेरी का उपयोग करना होगा।
रेल में JSON कॉलम
json
. बनाने के लिए रेल का समर्थन है (और jsonb
PostgreSQL पर) माइग्रेशन में कॉलम:
class CreateItems < ActiveRecord::Migration[7.0]
def change
create_table :items do |t|
t.jsonb :user_attributes
...
end
end
end
इस कॉलम को पढ़ते समय, लौटा हुआ परिणाम हैश होता है:
> Item.first.user_attributes
Item Load (0.6ms) SELECT "items".* FROM "items" ORDER BY "items"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> {"color"=>"text-red-400"}
> Item.first.update!(user_attributes: {color: "text-blue-400"})
> Item.first.user_attributes.dig(:color)
=> "text-blue-400"
अब जब हमारे पास हैश विशेषता है, तो आप मान पढ़ने/लिखने के लिए मॉडल में कुछ सहायक विधियों को जोड़ने के लिए प्रेरित हो सकते हैं:
class Item < ApplicationRecord
def color=(value)
self.user_attributes["color"] = value
end
def color
user_attributes.dig("color")
end
end
इस तरह के तरीके पूरी तरह से अच्छी तरह से काम करते हैं, लेकिन अगर आपके पास निपटने के लिए बहुत सारी JSON कुंजियाँ हैं, तो वे जल्दी से बोझिल हो सकती हैं; सौभाग्य से, रेल ने हमें कवर किया है।
ActiveRecord का स्टोर और store_accessor
डेटाबेस में JSON को संग्रहीत करने के दो पहलू हैं:क्रमांकन और पहुँच। अगर आप json
. का इस्तेमाल कर रहे हैं अपने डेटाबेस में कॉलम टाइप करें, तो आपको क्रमबद्धता पहलू के बारे में चिंता करने की आवश्यकता नहीं है। रेल और डेटाबेस एडेप्टर इसे आपके लिए संभाल लेंगे (आप सीधे store_accessor
. पर जा सकते हैं ) यदि आप टेक्स्ट कॉलम में डेटा स्टोर कर रहे हैं, तो ActiveRecord का store
विधि आपके लिए है, जो यह सुनिश्चित करती है कि आपके द्वारा कॉलम में लिखे गए डेटा को आपके चुने हुए प्रारूप में क्रमबद्ध किया गया है।
ActiveRecord का स्टोर
ActiveRecord में एक store
है हमारे द्वारा पढ़े या लिखे गए डेटा को अपने कॉलम में स्वचालित रूप से क्रमबद्ध करने की विधि:
class Item < ApplicationRecord
store :user_attributes, accessors: [:color], coder: JSON
end
यहां, :user_attributes
वह कॉलम है जिसका हम उपयोग करना चाहते हैं, जबकि accessors
उन चाबियों की सूची है जिन्हें हम एक्सेस करना चाहते हैं (बस color
यहां हमारे मामले में), और अंत में, हम निर्दिष्ट करते हैं कि हम डेटा को कैसे एन्कोड करना चाहते हैं। हम JSON का उपयोग कर रहे हैं, लेकिन आप यहां अपनी पसंद की किसी भी चीज़ का उपयोग कर सकते हैं, जिसमें YAML या कस्टम एन्कोडिंग जैसी चीज़ें शामिल हैं। यह विधि केवल क्रमांकन (आपके चुने हुए कोडर के साथ) को संभालती है और store_accessor
. को कॉल करती है हुड के नीचे।
ActiveRecord का store_accessor
हम store_accessor
. का उपयोग करके अपने मॉडल में गेट/सेट विधियाँ बनाते हैं :
class Item < ApplicationRecord
store_accessor :user_attributes, :color
store_accessor :user_attributes, :name, prefix: true
store_accessor :user_attributes, :location, prefix: 'primary'
end
यहाँ फिर से, user_attributes
वह डेटाबेस कॉलम है जिसका हम उपयोग करना चाहते हैं, उसके बाद कुंजी जिसे हम JSON डेटा में उपयोग करना चाहते हैं, और अंत में, हमारे पास उपसर्ग (या प्रत्यय) का उपयोग करने का विकल्प है। ध्यान दें कि store_accessor
नेस्टेड डेटा का समर्थन नहीं करता, केवल शीर्ष-स्तरीय कुंजी-मूल्य जोड़े। prefix
और suffix
विकल्प या तो एक बूलियन, स्ट्रिंग या प्रतीक लेते हैं। अगर एक बूलियन true
पारित हो जाता है, तो कॉलम का नाम उपसर्ग/प्रत्यय के रूप में प्रयोग किया जाता है।
=>item = Item.create!(color: 'red', user_attributes_name: 'Jonathan', primary_location: 'New Zealand')
>#<Item:0x000055d63f4f0360
id: 4,
user_attributes: {"color"=>"red", "name"=>"Jonathan", "location"=>"New Zealand"}>
=>item.color
>"red"
=> item.user_attributes_name
>"Jonathan"
=> item.name
>NoMethodError: undefined method `name'...
=> item.primary_location
>"New Zealand"
असली दुनिया में इस्तेमाल
मुझे कभी-कभी विशिष्ट ज्ञात-आगे-समय के संबंधपरक डेटाबेस स्कीमा से भटकने की आवश्यकता होती है। मेरे पास जितनी बार है, उसने इन विकल्पों के बिना डेटाबेस संरचना को क्लीनर और सरल दोनों बना दिया है।
एक उदाहरण जो मैंने देखा है वह कई एपीआई का समर्थन कर रहा है जहां उपयोगकर्ता अपने खातों को जोड़ता है। यह मुश्किल हो जाता है जब एपीआई समान प्रमाणीकरण योजनाओं का उपयोग नहीं करते हैं। कुछ उपयोगकर्ता नाम + पासवर्ड का उपयोग कर सकते हैं, जबकि अन्य एपीआई कुंजी का उपयोग कर सकते हैं, और अभी भी अन्य के पास एपीआई कुंजी, गुप्त और मर्चेंट आईडी है। एक तरीका यह है कि तालिका में कॉलम जोड़ते रहें, जहां उनमें से कई null
होंगे अधिकांश प्रदाताओं के लिए। json
का उपयोग करना , हालांकि, हम केवल उन्हीं मानों को संग्रहीत कर सकते हैं जिनकी किसी विशेष API को आवश्यकता होती है।
एक साइड प्रोजेक्ट जिस पर मैं काम कर रहा हूं, वह JSON स्टोरेज का भी उपयोग करता है ताकि उपयोगकर्ता उपयोगकर्ता द्वारा परिभाषित विशेषताओं सहित आइटम पर मनमानी विशेषताओं को सेट कर सकें। इस डेटा की तरलता और अप्रत्याशित प्रकृति को देखते हुए, JSON स्टोरेज जैसा कुछ (store_accessor
. के साथ) s ज्ञात विशेषताओं के लिए) एक स्वाभाविक फिट है।
सारांश
JSON डेटा (और इसके आस-पास ActiveRecord के सहायक) बहुत उपयोगी हो सकते हैं जब डेटा और डेटा संरचना परिवर्तनशील या अनजान हो। बेशक, इस तरह का डेटा स्टोरेज, ज्यादातर चीजों की तरह, एक ट्रेड-ऑफ है। जब आप विशेष रिकॉर्ड के लिए डेटा संरचना में बहुत अधिक लचीलापन प्राप्त करते हैं, तो आप कुछ डेटा अखंडता को छोड़ देते हैं जो डेटाबेस की कमी आपको दे सकती है। आप विशिष्ट ActiveRecord क्वेरीज़, जॉइन आदि के साथ रिकॉर्ड में क्वेरी करने की अपनी क्षमता को भी कम करते हैं।
अंगूठे के कुछ नियम यहां दिए गए हैं, यदि आप:
- जानें कि JSON कुंजियां सभी पंक्तियों के लिए समान होंगी, या
- किसी अन्य डेटाबेस तालिका की आईडी (प्राथमिक कुंजी) संग्रहीत कर रहे हैं, या
- JSON में किसी तालिका से रिकॉर्ड देखने के लिए उपयोग किए गए मान को संग्रहीत कर रहे हैं
फिर, आप एक नई तालिका बनाने से बेहतर हो सकते हैं जो आपके लिए डेटा अखंडता को लागू करने के लिए डेटाबेस का लाभ उठा सके। यदि, हालांकि, आप पंक्ति-विशिष्ट डेटा संग्रहीत कर रहे हैं जो सीधे अन्य तालिकाओं से संबंधित नहीं है, तो JSON आपकी डेटाबेस संरचना को सरल बनाने में आपकी सहायता कर सकता है।