1. انٹٹٹی اور ایسوسی ایشن کی بنیادی تصورات

ent فریم ورک میں، انٹٹٹی ڈیٹا بیس میں منظم کی جانے والی بنیادی ڈیٹا یونٹ ہوتی ہے، جو عام طور پر ڈیٹا بیس میں ایک ٹیبل کے مطابقت رکھتی ہے۔ انٹٹٹی میں فیلڈز ٹیبل کے کالمز کے مطابقت رکھتے ہیں، جبکہ انٹٹٹی کے درمیان رشتے (edges) انٹٹٹیز کے درمیان تعلقات اور تابعیت کو واضح کرنے کے لیے استعمال ہوتے ہیں۔ انٹٹٹی ایسوسی ایشنز مکمل ڈیٹا ماڈل بنانے کی بنیاد فراہم کرتے ہیں، جو والد - بچہ کے رشتے اور مالکیت کے رشتے وغیرہ جیسے نظامات کی تشریح کے لیے استعمال ہوتے ہیں۔

ent فریم ورک میں ایک مضبوط API سیٹ فراہم کی جاتی ہے، جو ڈیٹا سکیما میں ان ایسوسی ایشنز کو تعریف اور منظم کرنے کے لیے ڈویلپرز کو انتظام دینے کا امکان فراہم کرتی ہے۔ ان ایسوسی ایشنز کے ذریعے ہم کمپلیکس بزنس لاجک کو آسانی سے ظاہر کر سکتے ہیں اور اس پر کام کر سکتے ہیں۔

2. ent میں انٹٹٹی ایسوسی ایشنز کے اقسام

2.1 ایک سے ایک (O2O) ایسوسی ایشن

ایک سے ایک ایسوسی ایشن دو انٹٹٹیز کے درمیان ایک سے ایک مطابقت کو ظاہر کرتی ہے۔ مثال کے طور پر، صارفین اور بینک اکاؤنٹس کے معاملے میں، ہر صارف کے پاس صرف ایک بینک اکاؤنٹ ہوتا ہے، اور ہر بینک اکاؤنٹ بھی صرف ایک ہی صارف کا ہوتا ہے۔ ent فریم ورک edge.To اور edge.From میتھڈس کا استعمال اس طرح کی ایسوسی ایشن تعریف کرنے کے لیے کرتا ہے۔

پہلے، ہم User اسکیما کے اندر Card کی جانب ایک سے ایک ایسوسی ایشن کو تعریف کر سکتے ہیں۔

// صارف کے ایجز۔
func (User) Edges() []ent.Edge {
    return []ent.Edge{
        edge.To("card", Card.Type). // کارڈ انٹٹٹی کی جانب اشاره کرتا ہے، جو اسوسی ایشن کا نام "کارڈ" کے طور پر تعین کرتا ہے
            Unique(),                // یہ یونیک میتھڈ یہ یقینی بناتی ہے کہ یہ ایک سے ایک ایسوسی ایشن ہے
    }
}

اس کے بعد، ہم Card اسکیما کے اندر واپسی ایسوسی ایشن کو تعریف کر سکتے ہیں:

// کارڈ کے ایجز۔
func (Card) Edges() []ent.Edge {
    return []ent.Edge{
        edge.From("owner", User.Type). // کارڈ سے واپس صارف کی جانب پوائنٹ کرتا ہے، اس ایسوسی ایشن کا نام "مالک" کے طور پر تعین کرتا ہے
            Ref("card").               // ریف میتھڈ متناسب واپسی ایسوسی ایشن کا نام مخصوص کرتا ہے
            Unique(),                  // ایک مالک کے لیے یہ یونیک ہونے کی یقینی بناتی ہے
    }
}

2.2 ایک سے بہت (O2M) ایسوسی ایشن

ایک سے بہت ایسوسی ایشن بتاتی ہے کہ ایک انٹٹٹی کو متعدد دیگر انٹٹٹیز سے منسلک کیا جا سکتا ہے، لیکن یہ انٹٹٹیز صرف ایک انٹٹٹی کو پوائنٹ کر سکتی ہیں۔ مثال کے طور پر، ایک صارف کے پاس متعدد پالتو جانور ہو سکتے ہیں، لیکن ہر جانور کا صرف ایک مالک ہوتا ہے۔

ent میں، ہم اس قسم کے ایسوسی ایشن کی تعریف کرنے کے لیے بھی edge.To اور edge.From کا استعمال کرتے ہیں۔ نیچے دی گئی مثال میں صارفین اور پالتو جانوروں کے درمیان ایک سے بہت ایسوسی ایشن کو تعریف کرتی ہے:

// صارف کے ایجز۔
func (User) Edges() []ent.Edge {
    return []ent.Edge{
        edge.To("pets", Pet.Type), // صارف انٹٹٹی سے پالتو جانوروں تک کا ایک سے بہت ایسوسی ایشن
    }
}

پیٹ انٹٹٹی میں، ہم User کی طرف واپسی ایسوسی ایشن کی تعریف کرتے ہیں:

// پیٹ کے ایجز۔
func (Pet) Edges() []ent.Edge {
    return []ent.Edge{
        edge.From("owner", User.Type). // پیٹ سے صارف کی جانب بہت سے ایک ایسوسی ایشن کی تعریف کرتا ہے
            Ref("pets").              // پیٹ سے واپسی ایسوسی ایشن کا نام تعین کرتا ہے
            Unique(),                 // یہ یونیک بناتا ہے کہ ایک مالک کے پاس متعدد پالتو جانور ہو سکتے ہیں
    }
}

2.3 بہت سے بہت (M2M) ایسوسی ایشن

بہت سے بہت ایسوسی ایشن دو قسم کی انٹٹٹیز کو ایک دوسرے کے متعدد انسٹنسز ہونے کا امکان فراہم کرتا ہے۔ مثال کے طور پر، ایک طالب علم متعدد کورسز میں رجسٹر ہو سکتا ہے، اور ایک کورس بھی متعدد طالبین کو رجسٹر کروا سکتا ہے۔ ent کورس کے ساتھ بہت سے بہت ایسوسی ایشن قائم کرنے کے لیے ایک اے پی فراہم کرتا ہے۔

Student انٹٹٹی میں، ہم Course کے ساتھ بہت سے بہت ایسوسی ایشن قائم کرنے کے لیے edge.To کا استعمال کرتے ہیں:

// طالب علم کے ایجز۔
func (Student) Edges() []ent.Edge {
    return []ent.Edge{
        edge.To("courses", Course.Type), // طالب علم سے کورس کے درمیان بہت سے بہت ایسوسی ایشن کی تعریف کرتا ہے
    }
}

اسی طرح، Course انٹٹی میں، ہم بہت سے بہت رشتہ کے لیے Student کی طرف واپسی ایسوسی ایشن قائم کرتے ہیں:

// کورس کے ایجز۔
func (Course) Edges() []ent.Edge {
    return []ent.Edge{
        edge.From("students", Student.Type). // کورس سے طالب علم کی جانب بہت سے بہت ایسوسی ایشن کی تعریف کرتا ہے
            Ref("courses"),                 // کورس سے طالب علم کی جانب واپسی ایسوسی ایشن کا نام تعین کرتا ہے
    }
}

یہ قسم کے ایسوسی ایشنز کمپلیکس ایپلیکیشن ڈیٹا ماڈل بنانے کی بنیاد ہیں، اور یہ سمجھنا کہ ان کو ent میں کیسے تعریف اور استعمال کیا جایے ان ڈیٹا ماڈل اور بزنس لاجک کو توسیع دینے کے لیے نہایت اہم ہے۔

3. موجودہ رشتوں کے لیے بنیادی عملیات کا عمل

اس سیکشن میں ent کا استعمال کرتے ہوئے بنائی گئی تعلقات کے ساتھ بنیادی عملیات کی تھاکیک کرانے کا طریقہ دکھایا جائے گا، جس میں موجودہ کرنا، سوال کرنا اور منسلک انٹٹیٹیز کے ساتھ سفر کرنا شامل ہے۔

3.1 منسلک انٹٹیٹیز کا بنانا

انٹٹیٹیز بناتے وقت، آپ ایک ساتھ ہی انٹٹیٹیز کے درمیان تعلقات بھی تعین کرسکتے ہیں۔ ایک سے بہت سارے (O2M) اور بہت سے بہت سارے (M2M) تعلقات کے لئے، آپ منسلک انٹٹیٹیز شامل کرنے کے لیے Add{Edge} میتھڈ کا استعمال کرسکتے ہیں۔

مثال کے طور پر، اگر ہمارے پاس ایک صارف کی انٹٹیٹی اور ایک پالتو جانور کی انٹٹیٹی ہوتی ہے اور ان کا کوئی تعلق ہوتا ہے، جہاں ایک صارف کے پاس متعدد جانور ہوسکتے ہیں، تو نیچے دی گئی مثال میں ایک نیا صارف بنانا اور ان کے لئے جانور شامل کرنا ہے:

// ایک صارف بنانا اور جانور شامل کرنا
func CreateUserWithPets(ctx context.Context, client *ent.Client) (*ent.User, error) {
    // جانور کا مواقع بنانا
    fido := client.Pet.
        Create().  
        SetName("فیدو").
        SaveX(ctx)
    // صارف کا مواقع بنانا اور جانور کے ساتھ منسلک کرنا
    user := client.User.
        Create().
        SetName("ایلس").
        AddPets(fido). // جانور کو منسلک کرنے کے لیے AddPets میتھڈ کا استعمال کریں
        SaveX(ctx)

    return user, nil
}

اس مثال میں، ہم پہلے فیدو نام کا جانور بناتے ہیں، پھر ایلس نام کے صارف کا مقام بناتے ہیں اور AddPets میتھڈ کا استعمال کرکے صارف کے ساتھ جانور کو منسلک کرتے ہیں۔

3.2 منسلک انٹٹیٹیز کا سوال کرنا

منسلک انٹٹیٹیز کا سوال کرنا ent میں ایک عام عمل ہے۔ مثال کے طور پر، آپ مخصوص انٹٹیٹی کے ساتھ منسلک دیگر انٹٹیٹیز کو حاصل کرنے کے لیے Query{Edge} میتھڈ کا استعمال کرسکتے ہیں۔

ہمارے صارفوں اور جانوروں کی مثال جاری رکھتے ہوئے، نیچے دی گئی کوڈ مثال میں دیکھ سکتے ہیں کہ ایک صارف کے پاس تمام جانوروں کو کیسے سوال کیا جائے:

// ایک صارف کے تمام جانوروں کا سوال کرنا
func QueryUserPets(ctx context.Context, client *ent.Client, userID int) ([]*ent.Pet, error) {
    pets, err := client.User.
        Get(ctx, userID). // صارف کا مواقع حاصل کرنے کے لیے صارف ID کے بناۓ گئے مواقع کا استعمال کریں
        QueryPets().      // صارف کے ساتھ منسلک جانور کی انٹٹیٹیز کا سوال کریں
        All(ctx)          // سوال کردہ تمام جانور کی انٹٹیٹیز واپس آئیں
    if err != nil {
        return nil, err
    }

    return pets, nil
}

اوپر کے کوڈ سنیپٹ میں، ہم پہلے صارف کے مواقع کو صارف ID کے بناۓ گئے مواقع سے حاصل کرتے ہیں، پھر QueryPets میتھڈ کو بلا رہے ہیں تاکہ اس صارف کے ساتھ منسلک تمام جانور کی انٹٹیٹیز حاصل کی جا سکیں۔

یاد رہے: ent کا کوڈ جنریشن ٹول تعلقات کی تعریف پر مبنی سوال کے API خود بخود تشکیل دیتا ہے۔ اس کی منظوری کرنا مشورہ ہے۔

4. جلدی لوڈنگ

4.1 پریلوڈنگ کے اصول

پریلوڈنگ کو سوالیہ ڈیٹا بیس کو سوال کرنے کے لیے ایک کنیکٹیکنیک بنایا ہے تاکہ پہلے ہی سے منسلک انٹٹیٹیز کو فیچ اور لوڈ کیا جا سکے۔ یہ تکنیک مختلف انٹٹیٹیز سے متعلق ڈیٹا کو ایک ہی وقت میں حاصل کرنے کے لئے استعمال ہوتی ہے، تاکہ آگے کی پروسیسنگ میں متعدد ڈیٹا بیس کی سوالیہ کارروائیوں سے بچا جا سکے، جس سے ایپلیکیشن کی کارکردگی کو بہتر کیا جا سکے۔

ent فریم ورک میں پریلوڈنگ کو بنیادی طور پر انٹٹیٹیز کے درمیان تعلقات، مثلاً ایک سے بہت سارے اور بہت سے بہت سارے کے لیے استعمال کیا جاتا ہے۔ ڈیٹا بیس سے ایک انٹٹیٹی کو حاصل کرتے وقت، اس کے منسلک انٹٹیٹیز خود بخود لوڈ نہیں ہوتیں۔ بلکہ یہ بطور سرعی پر پریلوڈنگ کی حیثیت سے یقینی بناتے ہیں۔ یہ N+1 سوالیہ (یعنی ہر پیرنٹ انٹٹیٹی کے لئے الگ الگ سوال کرنا) کو دور کرنے کے لیے اہم ہے۔

ent فریم ورک میں پریلوڈنگ کی تکنیک کو query builder میں With میتھڈ کا استعمال کرکے حاصل کیا جاتا ہے۔ یہ میتھڈ انٹٹیٹیز کے ہر edge کے لیے مطابقتی With... فنکشنز کو پیدا کرتا ہے، جیسے کہ WithGroups اور WithPets۔ یہ میتھڈز ent فریم ورک کی طرف سے خود بخود تشکیل دیتے ہیں، اور پروگرامر ان کو مختصران مطالبت کے لیے استعمال کرسکتے ہیں تاکہ وہ خاص تعلقات کو حاصل کرنے کا درخواست کر سکیں۔

انٹٹیٹیز کو پریلوڈ کرنے کا عمل کا عملی اصول یہ ہے کہ جب اصل انٹٹیٹی کو سوال کرتے ہیں، تو ent نے سب سے زیادہ منسلک انٹٹیٹیز کو حاصل کرنے کے لیے اضافی سوالیہ کارروائی کرتا ہے۔ اس کے بعد، یہ انٹٹیٹیز کو واپسی آئیٹم کے Edges فیلڈ میں بھر دیتا ہے۔ یعنی ent نے کم سے کم ایک سے زیادہ منسلک edge کے لیے کم از کم ایک ڈیٹا بیس سوالیہ کیا ہوتا ہے۔ جبکہ یہ میتھڈ کسی چند مخصوص سیٹویشنز میں ایک ہی مشکل JOIN کوئیری سے کم موثر ہوسکتا ہے، لیکن یہ زیادہ فلیکسیبلیت فراہم کرتا ہے اور متوقع ہے کہ اسے انٹٹیٹی کی سرگرمیوں میں بہتری کرنے کی محتمل جوڑ کے نسخے میں استعمال کیا جائے گا۔

4.2 پریلوڈنگ کا عمل

اب ہم واضح کروانے کیلئے دیگئیے گئے ماڈل کے ذریعے ent فریم ورک میں پریلوڈنگ عمل کرنے کا عمل دکھائیں گے۔

ایک ہی رشتے کو پیش کرنا

تصور کریں ہمیں ڈیٹا بیس سے تمام صارفین کو حاصل کرنا ہو اور پالتو جانوروں کے ڈیٹا کو پیش کرنا ہو۔ ہم مندرجہ ذیل کوڈ لکھ کر اس کو حاصل کر سکتے ہیں:

users, err := client.User.
    Query().
    WithPets().
    All(ctx)
if err != nil {
    // خرابی کا سامنا کریں
    return err
}
for _, u := range users {
    for _, p := range u.Edges.Pets {
        fmt.Printf("صارف (%v) کے پاس جانور (%v) ہے\n", u.ID, p.ID)
    }
}

اس مثال میں ہم WithPets میتھڈ استعمال کرتے ہیں تاکہ ent سے صارفین کے ساتھ منسلک پالتو جانوروں کو پیش کریں۔ پیش کردہ پالتو جانوروں کے ڈیٹا کو Edges.Pets فیلڈ میں بھرا جاتا ہے، جس سے ہم اس منسلک ڈیٹا تک رسائی حاصل کر سکتے ہیں۔

متعدد منسلکوں کو پیش کرنا

ent ہمیں ایک ہی وقت میں متعدد منسلکوں کو پیش کرنے دیتا ہے، اور حتیٰ چاہے تو تعلقات کو پیش کرنے کے بعد منسلکوں کو باقاعدہ کرنے،ترتیب دینے یا پیش کردہ نتائج کی تعداد محدود کرنے کا بھی مشیر ہے۔ نیچے ایک مثال ہے جس میں منسلک انتظامیں کے پالتو جانوروں کو پیش کرنے، ان کی ٹیموں کو جنہیں وہ تعلق رکھتے ہیں کو پیش کرنے، جبکہ ٹیموں کے ساتھ منسلک صارفین کو بھی پیش کرنے کا کام ہے۔

admins, err := client.User.
    Query().
    Where(user.Admin(true)).
    WithPets().
    WithGroups(func(q *ent.GroupQuery) {
        q.Limit(5)          // پہلے 5 ٹیموں تک محدود کریں
        q.Order(ent.Asc(group.FieldName)) // ٹیم کے نام کے ترتیب کی بنیاد پر ترتیب دیں
        q.WithUsers()       // ٹیم میں صارفین کو پیش کریں
    }).
    All(ctx)
if err != nil {
    // خرابیوں کا سامنا کریں
    return err
}
for _, admin := range admins {
    for _, p := range admin.Edges.Pets {
        fmt.Printf("منتظم (%v) کے پاس جانور (%v) ہے\n", admin.ID, p.ID)
    }
    for _, g := range admin.Edges.Groups {
        fmt.Printf("منتظم (%v) ٹیم (%v) کا حصہ ہے\n", admin.ID, g.ID)
        for _, u := range g.Edges.Users {
            fmt.Printf("ٹیم (%v) میں رکن (%v) ہے\n", g.ID, u.ID)
        }
    }
}

اس مثال کے ذریعے، آپ دیکھ سکتے ہیں کہ ent کتنا طاقتور اور متنوع ہے۔ کچھ آسان میتھڈ کالز کے ذریعے، یہ مضبوط منسلک ڈیٹا کو پیش کر سکتا ہے اور انہیں ایک منظم طریقے سے منظم کر سکتا ہے۔ یہ ڈیٹا سے چلنے والے ایپلیکیشنز کے لیے عظیم سہولت فراہم کرتا ہے۔