Jsonb


PostgresSQL এ JSON ডাটা টাইপ ব্যবহার করা হয় json ডাটা জমা রাখতে। Json ডাটা টেক্স টাইপ এর মাধ্যমেও রাখা যায়। তবে JSON ডাটা টাইপ ব্যবহার করলে ডাটা অবশ্যই একটা ভ্যালিড json হতে হবে। PostgresSQL দুই ধরনের json টাইপ আছে 

json

- jsonb


json  এবং jsonb প্রায় একই জিনিষ, তাদের মধ্যে পার্থক্য শুধু ইফিসিয়েনসিতে। json কে যেভাবে ইনপুট দেয়া হয় ঠিক সেভাবেই জমা রাখা হয়, কিন্তু প্রতিবার ডাটা তোলার সময় সেই ডাটাকে রিপার্স করতে হয়। অন্যদিকে jsonb ডাটাকে জমা করার সময় বাইনারী করে জমা করা হয় তারপর আর রিপার্স করার দরকার পরে না। তাই jsonb রাইট স্লো বাট রিড ফাস্ট। jsonb এর ফিল্ড কিন্তু  ইনডেক্স সাপোর্ট করে, মনে ফিল্ডকে ইনডেক্স করা যায়।


যেহেতু json ডাটা টাইপ এক্সাক্ট কপি জমা রাখে, তাই ডাটাবেসে হোয়াইট স্পেস জমা থাকে,  একই Key একাধিকবার থাকতে পারে এবং সবকিছু যেভাবে ইনপুট দেয়া হয় সেভাবেই আউটপুট দেয়া হয়।   

অন্যদিকে jsonb তে হোয়াইট স্পেস জমা রাখে না এবং একই Key একাধিকবার থাকে না,  একই Key একাধিকবার দিলে শুধু শেষেরটা জমা রাখে এবং  jsonb  Key এর সিরিয়াল মনে রাখে না।  তাই যদি কোন স্পেশাল কেস না থাকে, তাহলে json  ডাটা জমা রাখার জন্য jsonb টাইপ ব্যবহার করা উচিৎ। তাই যখন jsonb টাইপ ডাটা সেভ করা হয় তখন json  এর ভিতরের ডাটা PostgresSQL এর টাইপেই সেভ করা হয়। মনে হচ্ছে যদি json এর ভিতর {id: 1} থাকে, তাহলে 1 কে number হিসাবে সেভ করা হবে। 


GIN Index ব্যবহার করা হয় jsonb এর Key বা Key/Value ইনডেক্স করতে। ধরি, আমাদের একটা টেবিল আছে api নামে এবং এর একটা jsonb কলাম আছে jodc নামে এবং jodc এর স্ট্রাকচার দেখতে নিচের মতো 

{
    "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
    "name": "Angela Barton",
    "is_active": true,
    "company": "Magnafone",
    "address": "178 Howard Place, Gulf, Washington, 702",
    "registered": "2009-11-07T08:53:22 +08:00",
    "latitude": 19.793713,
    "longitude": 86.513373,
    "tags": [
        "enim",
        "aliquip",
        "qui"
    ]
}

তাহলে index করতে হলে 

CREATE INDEX idxgin ON api USING GIN (jdoc);

আবার jsonb_path_ops অপারেটর ক্লাস যোগ করেও ইনডেক্স করতে পারি, এক্ষেত্রে আমরা key-exists অপারেটর ব্যবহার করতে পারব। 

CREATE INDEX idxginp ON api USING GIN (jdoc jsonb_path_ops);

আবার আমরা চাইলে tag কে আলাদা ইনডেক্স করে নিতে পারি 

CREATE INDEX idxgintags ON api USING GIN ((jdoc -> 'tags'));


এখন কিছু কুয়েরী দেখা যাক 

১। এমন ডকুমেন্ট সিলেক্ট কর যেখানে Key হচ্ছে "company" এবং ভ্যালু হচ্ছে "Magnafone"

SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}';


২। এমন ডকুমেন্ট সিলেক্ট কর যেখানে Key হচ্ছে 'tags' এবং ভ্যালু হচ্ছে একটা একটা ট্যাগ নাম 'qui'

SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui';

বা 

SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}';