DailyWatch میں، ہمارا "related videos" پینل ایک سادہ SQLite کوئری سے شروع ہوا۔ اس نے تین ٹیبلز کو جوڑا، ایک جیسے ٹیگز کی گنتی کی، اور ایک درجہ بندی شدہ فہرست فراہم کی۔ ایک چھوٹے کیٹلاگ کے لیے، یہ کافی تھا۔ "italian" اور "pasta" ٹیگز والی ایک کوکنگ ویڈیو وہی ٹیگز رکھنے والی دیگر ویڈیوز کو سامنے لاتی تھی، اور صارفین ان پر کلک کرتے تھے۔ آؤٹ پٹ متعلقہ لگتا تھا کیونکہ میٹا ڈیٹا صاف ستھرا تھا اور لائبریری محدود تھی۔

پھر کیٹلاگ بڑھا، اور سامعین کی توقعات بدل گئیں۔ لوگ صرف ایک جیسے ٹیگز والی مزید ویڈیوز نہیں چاہتے تھے۔ وہ وہ کلپ چاہتے تھے جسے چالیس فیصد ناظرین موجودہ ویڈیو کے فوراً بعد دیکھتے تھے۔ وہ وہ مخصوص (niche) چینل چاہتے تھے جو ایک ہی دیر رات کے دیکھنے کے سیشنز میں بار بار سامنے آتا تھا، چاہے اس کی تفصیل میں شروع ہونے والی ویڈیو کا کوئی ذکر نہ ہو اور اس کے ٹیگز بھی نہ ہونے کے برابر ہوں۔ یہ رویوں کے نمونے (behavioral patterns) ہیں، میٹا ڈیٹا کا ملاپ نہیں۔ SQLite ان کو self-joins اور recursive common table expressions کے ایک ناقابلِ برقرار پیچیدہ جال کے بغیر بیان نہیں کر سکتا تھا۔ ہر نیا سگنل جسے ہم ماڈل کرنے کی کوشش کرتے، چاہے وہ co-viewership ہو یا session adjacency، لیٹنسی (latency) اور ذہنی بوجھ میں اضافہ کرتا تھا۔ ہمارے پاس ایک گراف کا مسئلہ تھا جسے ریلیشنل (relational) ڈھانچے میں ٹھونسنے کی کوشش کی جا رہی تھی۔

میں نے recommendation layer کو Apache AGE پر منتقل کر دیا۔

Apache AGE ایک PostgreSQL extension ہے جو آپ کے پہلے سے چلنے والے ڈیٹا بیس میں openCypher graph queries کا اضافہ کرتا ہے۔ یہ کوئی الگ سرور نہیں ہے۔ یہ کوئی sidecar نہیں ہے۔ یہ Postgres کے اندر چلتا ہے، جس کا مطلب یہ تھا کہ ہم ایک وقف (dedicated) Neo4j cluster قائم کیے بغیر یا مکمل طور پر نیا آپریشنل طریقہ کار سیکھے بغیر ایک co-view network بنا سکتے تھے۔ ڈیٹا بیس ریلائبلٹی انجینئر کے بغیر ایک چھوٹی ٹیم کے لیے، یہ فرق بہت اہمیت رکھتا تھا۔

کیوں ایک Extension ایک نئے ڈیٹا بیس سے بہتر ہے

اپنے اسٹیک میں گراف ڈیٹا بیس کا اضافہ وائٹ بورڈ پر تو آسان ہے لیکن پروڈکشن میں مہنگا پڑتا ہے۔ آپ کو نئے مانیٹرنگ ڈیش بورڈز، نئے بیک اپ طریقہ کار، نئے کنکشن پولز، اور نئے failover لاجک کی ضرورت ہوتی ہے۔ AGE ان سب سے بچتا ہے کیونکہ یہ آپ کے موجودہ Postgres instance کے اندر رہتا ہے۔

اس کے ہمارے لیے کام کرنے کی چار عملی وجوہات ہیں۔

  • کوئی نیا انفراسٹرکچر نہیں۔ چونکہ AGE ایک extension ہے، اس لیے آپ کا موجودہ pg_dump شیڈول، آپ کے موجودہ ریپلیکا (replicas)، اور آپ کے معیاری Postgres ہیلتھ چیکس سب کام کرتے رہیں گے۔ آپ کو آپریشنز ٹیم کو ایک اور ڈیٹا اسٹور کی دیکھ بھال کے لیے قائل کرنے کی ضرورت نہیں ہے۔
  • ایک ہی کوئری میں مکسڈ ورک لوڈز۔ AGE آپ کو SQL کے اندر Cypher لکھنے کی اجازت دیتا ہے۔ آپ امیدوار ویڈیوز تلاش کرنے کے لیے graph traversal چلا سکتے ہیں، پھر اس رزلٹ سیٹ کو اپنے ریلیشنل users ٹیبل کے ساتھ جوڑ سکتے ہیں تاکہ علاقائی مواد کی پابندیوں کو نافذ کیا جا سکے، یا کسی ریلیشنل sponsorships ٹیبل کے ساتھ جوڑ سکتے ہیں تاکہ مخصوص چینلز کو کم ترجیح دی جا سکے۔ ایک راؤنڈ ٹرپ۔ دو کوئری زبانیں مل کر کام کر رہی ہیں۔
  • پورٹیبلٹی (Portability)۔ Cypher ایک اوپن اور اچھی طرح سے دستاویزی (well-documented) گراف کوئری زبان ہے۔ اگر DailyWatch کو AGE سے زیادہ ضرورت ہو اور بعد میں Neo4j یا Memgraph پر منتقل ہونے کی ضرورت پڑے، تو کوئری لاجک کو کم سے کم دوبارہ لکھنے کے ساتھ منتقل کیا جا سکتا ہے۔ آپ کسی مخصوص (proprietary) لہجے میں قید نہیں ہوتے۔
  • مطابقت (Compatibility)۔ چونکہ ڈیٹا بالآخر PostgreSQL میں رہتا ہے، اس لیے آپ کے موجودہ PHP یا Python ٹولنگ میں کوئی تبدیلی نہیں آتی۔ آپ اسی ڈرائیور سے منسلک ہوتے ہیں، انہی کنکشن اسٹرنگز کو ہینڈل کرتے ہیں، اور اسی طرح روز (rows) حاصل کرتے ہیں۔ گراف لاجک کوئری لیئر میں ہوتی ہے، ایپلیکیشن لیئر میں نہیں۔

Co-Viewership کی ماڈلنگ

اس کا نفاذ (implementation) سادہ ہے۔ ہم نے ان اداروں (entities) کے لیے نوڈز (nodes) متعین کیے جن کی ہمیں پرواہ تھی: Video اور Channel۔ پھر ہم نے ان کے درمیان تعلقات کے لیے ایجز (edges) متعین کیے۔ ایک PUBLISHED ایج ایک Channel کو ایک Video سے جوڑتی ہے۔ ایک CO_VIEWED ایج ایک Video کو دوسری سے جوڑتی ہے، جس میں ایک weight پراپرٹی ہوتی ہے جو یہ ظاہر کرتی ہے کہ وہ دو ویڈیوز کتنی بار ایک ہی دیکھنے کے سیشن میں نظر آئیں۔

یہ ماڈل اس چیز کو قید کرتا ہے جو ٹیگ پر مبنی SQL نہیں کر سکتا: پوشیدہ ساخت (implicit structure)