Postgres-এ Apache AGE ব্যবহার করে ভিডিওর সম্পর্ক অনুসন্ধান (Querying)
রিলেশনাল ডেটাবেসগুলো গভীর সম্পর্কের (deep relationships) ক্ষেত্রে হিমশিম খায়।
TrendVidStream-এ, আমরা আটটি অঞ্চলের স্ট্রিমিং টাইটেলের একটি ক্যাটালগ পরিচালনা করি। আমরা মূলত FTS5 সহ SQLite ব্যবহার করতাম। এটি ফুল-টেক্সট সার্চ এবং সহজ ডিপ্লয়মেন্টের জন্য ভালো কাজ করত।
সমস্যাটি শুরু হয় যখন ব্যবহারকারীরা জটিল প্রশ্ন করতে শুরু করেন। তারা জানতে চাইতেন: "এই নির্দিষ্ট পরিচালক এবং এই অভিনেতাদের এই থ্রিলার মুভিটির থেকে দুই বা তিন ধাপ (hop) দূরে আর কী কী আছে?"
SQL-এ, এর জন্য অনেকগুলো self-join প্রয়োজন হয়। প্রতিটি অতিরিক্ত ধাপ কুয়েরিকে রক্ষণাবেক্ষণ করা কঠিন করে তোলে এবং এর গতি কমিয়ে দেয়। জয়েন ফ্যান-আউট (join fan-out) একটি দুঃস্বপ্নে পরিণত হয়।
আমরা PostgreSQL-এ Apache AGE এক্সটেনশন ব্যবহার করে একটি গ্রাফ লেয়ার যুক্ত করার মাধ্যমে এটি সমাধান করেছি।
কেন এই বিভাজনটি কার্যকর, তার কারণগুলো নিচে দেওয়া হলো:
• আপনি PostgreSQL ব্যবহার করতে পারবেন। আপনি একই কানেকশন, ট্রানজ্যাকশন এবং ব্যাকআপ টুল ব্যবহার করতে পারবেন। আপনার Neo4j-এর মতো আলাদা কোনো ডেটাবেসের প্রয়োজন হবে না। • আপনি গ্রাফ এবং রিলেশনাল ডেটা মিশ্রিত করতে পারেন। আপনি Cypher কুয়েরি চালাতে পারেন এবং সেই ফলাফলগুলোকে স্ট্যান্ডার্ড SQL টেবিলের সাথে জয়েন করতে পারেন। • আপনি সহজেই পরিবর্তনশীল ডেপথ (variable depth) হ্যান্ডেল করতে পারেন। Cypher-এ এক থেকে তিন ধাপের মধ্যে সংযোগ খুঁজে বের করা একটি সহজ কমান্ড মাত্র। • আপনি সরলতা বজায় রাখতে পারেন। গ্রাফটি হলো আপনার ডেটার একটি প্রজেকশন, এটি কোনো আলাদা সোর্স অফ ট্রুথ (source of truth) নয়।
আমাদের মডেলে চারটি vertex label ব্যবহার করা হয়েছে:
- Video
- Person
- Platform
- Region
আমরা SIMILAR_TO, WORKED_ON, এবং AVAILABLE_IN-এর মতো নির্দিষ্ট edge type ব্যবহার করি।
একটি গুরুত্বপূর্ণ শিক্ষা: সবসময় আপনার এন্ট্রি পয়েন্টগুলো ইনডেক্স করুন। আমরা Video vertex-এর ext_id প্রপার্টি ইনডেক্স করি। এটি ছাড়া, প্রতিটি ট্রাভার্সাল (traversal) একটি ধীরগতির সিকোয়েন্সিয়াল স্ক্যান দিয়ে শুরু হয়।
এর ফলে রেকমেন্ডেশনের জন্য একটি পরিষ্কার এবং পঠনযোগ্য কুয়েরি পাওয়া যায়:
SELECT * FROM cypher('discovery', $$ MATCH (seed:Video {ext_id: 'vid_8842'}) MATCH (seed)-[:SIMILAR_TO|WORKED_ON*1..3]-(rec:Video)-[:AVAILABLE_IN]->(:Region {code: 'DE'}) WHERE rec.ext_id <> 'vid_8842' RETURN DISTINCT rec.ext_id, rec.title, rec.year LIMIT 24 $$) AS (ext_id agtype, title agtype, year agtype);
এই কুয়েরিটি তিন ধাপের মধ্যে জার্মানি (Germany) তে উপলব্ধ সম্পর্কিত ভিডিওগুলো খুঁজে বের করে। SQL-এ এটি হতো অনেকগুলো জয়েনের একটি বিশাল স্তূপ। Cypher-এ এটি একটি সাধারণ প্যাটার্ন মাত্র।
আমরা টেক্সট সার্চের জন্য SQLite রেখেছি এবং কানেক্টিভিটির জন্য AGE ব্যবহার করেছি। প্রতিটি টুল তার সেরা কাজটিই করছে।
