SQL कनेक्ट स्कीमा डिज़ाइन करना

Firebase SQL Connect की मदद से, GraphQL स्कीमा डिज़ाइन किया जा सकता है. यह स्कीमा, आपके ऐप्लिकेशन के लिए ज़रूरी डेटा मॉडल को दिखाता है. SQL Connect इस स्कीमा को PostgreSQL के लिए Cloud SQL इंस्टेंस में बदलता है. यह इंस्टेंस, आपके ऐप्लिकेशन को बैकअप देता है. इसके बाद, बैकएंड के साथ इंटरफ़ेस करने के लिए, क्वेरी और म्यूटेशन लिखे जाते हैं. साथ ही, क्लाइंट कोड से अपना डेटा इस्तेमाल करने के लिए, इन कार्रवाइयों को कनेक्टर में बंडल किया जाता है.

SQL Connect में एआई टूलिंग की सुविधा मिलती है. इससे स्कीमा डिज़ाइन करने और उन्हें लागू करने में मदद मिलती है. इस गाइड में, स्कीमा डिज़ाइन के अहम कॉन्सेप्ट के बारे में बताया गया है. इससे आपको ऐप्लिकेशन डेवलप करते समय, स्टैंडर्ड और एआई की मदद से किए जाने वाले वर्कफ़्लो को बेहतर बनाने और उन्हें पूरा करने में मदद मिलती है. साथ ही, यह सुविधा ऐप्लिकेशन डेवलप करने के बाद भी काम आती है. और .

शुरू करने के लिए गाइड में, PostgreSQL के लिए फ़िल्म की समीक्षा करने वाले ऐप्लिकेशन के स्कीमा के बारे में बताया गया है.

इस गाइड में, उस स्कीमा को और बेहतर बनाया गया है. साथ ही, फ़िल्म की समीक्षा करने वाले ऐप्लिकेशन के फ़ाइनल स्कीमा के बराबर SQL लिस्टिंग दी गई है.

फ़िल्म की समीक्षा करने वाले ऐप्लिकेशन का स्कीमा

मान लें कि आपको एक ऐसी सेवा बनानी है जिससे उपयोगकर्ता, फ़िल्मों की समीक्षाएं सबमिट और देख सकें.

इस तरह के ऐप्लिकेशन के लिए, बुनियादी क्वेरी को सपोर्ट करने वाला शुरुआती स्कीमा ज़रूरी है. बाद में, इस स्कीमा को बढ़ाकर, जटिल रिलेशनल क्वेरी बनाई जा सकती हैं.

SQL Connect में, GraphQL टाइप तय किए जाते हैं. इससे यह तय किया जाता है कि आपके क्लाइंट, किस तरह के डेटा के लिए क्वेरी कर सकते हैं और उसमें बदलाव कर सकते हैं. स्कीमा लिखते समय, आपके टाइप को PostgreSQL के लिए Cloud SQL टेबल में ट्रांसलेट किया जाता है. ज़्यादातर मामलों में, GraphQL टाइप और डेटाबेस टेबल के बीच सीधा संबंध होता है. हालांकि, अन्य मैपिंग भी की जा सकती हैं. इस गाइड में, बुनियादी से लेकर ज़्यादा बेहतर स्कीमा के कुछ उदाहरण दिए गए हैं.

Movie टाइप तय करना

Movie टाइप से शुरुआत की जा सकती है.

Movie के स्कीमा में, ये मुख्य डायरेक्टिव शामिल होते हैं:

  • SQL टेबल और कॉलम के नामों को पसंद के मुताबिक बनाने के लिए, @table(name) और @col(name). अगर नाम तय नहीं किए जाते हैं, तो SQL Connect snake_case फ़ॉर्मैट में नाम जनरेट करता है.
  • SQL कॉलम के टाइप को पसंद के मुताबिक बनाने के लिए, @col(dataType).
  • इंसर्ट करते समय, SQL कॉलम की डिफ़ॉल्ट वैल्यू कॉन्फ़िगर करने के लिए, @default.

ज़्यादा जानकारी के लिए, @table, @col, @default के रेफ़रंस दस्तावेज़ देखें.

# Movies
type Movie @table(name: "movie", key: "id") {
  id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
  title: String!
  releaseYear: Int
  genre: String @col(dataType: "varchar(20)")
  rating: Int
  description: String
}

User टाइप में, उपयोगकर्ता का अहम डेटा अपने-आप सेव करना

आपका ऐप्लिकेशन, उपयोगकर्ताओं की जानकारी ट्रैक करेगा. इसलिए, आपको User टाइप की ज़रूरत होगी.

इस मामले में, @default डायरेक्टिव खास तौर पर काम का है. यहां id फ़ील्ड, उपयोगकर्ता की आईडी को पुष्टि करने की प्रोसेस से अपने-आप फ़ेच कर सकता है. इसके लिए, यहां दिए गए उदाहरण में @default(expr: "auth.uid") का इस्तेमाल किया गया है.

# Users
# Suppose a user can leave reviews for movies
type User @table {
  id: String! @default(expr: "auth.uid")
  username: String! @col(dataType: "varchar(50)")
}

मुख्य स्केलर और सर्वर वैल्यू

फ़िल्म की समीक्षा करने वाले ऐप्लिकेशन के बारे में ज़्यादा जानने से पहले, SQL Connect मुख्य स्केलर और सर्वर वैल्यू के बारे में जानना ज़रूरी है.

मुख्य स्केलर, ऑब्जेक्ट के संक्षिप्त आइडेंटिफ़ायर होते हैं. SQL Connect इन्हें आपके स्कीमा में मौजूद मुख्य फ़ील्ड से अपने-आप इकट्ठा करता है. मुख्य स्केलर, डेटा की पहचान और स्ट्रक्चर के बारे में एक ही कॉल में जानकारी पाने में मदद करते हैं. इससे काम की रफ़्तार बढ़ती है. ये खास तौर पर तब काम के होते हैं, जब आपको नए रिकॉर्ड पर क्रम से कार्रवाइयां करनी होती हैं और आने वाली कार्रवाइयों के लिए, किसी यूनीक आइडेंटिफ़ायर की ज़रूरत होती है. साथ ही, जब आपको ज़्यादा जटिल कार्रवाइयां करने के लिए, रिलेशनल की ऐक्सेस करनी होती हैं.

सर्वर वैल्यू का इस्तेमाल करके, सर्वर को expr आर्ग्युमेंट में दिए गए, सर्वर-साइड CEL एक्सप्रेशन के मुताबिक, सेव की गई या आसानी से कैलकुलेट की जा सकने वाली वैल्यू का इस्तेमाल करके, आपकी टेबल में मौजूद फ़ील्ड को डाइनैमिक तरीके से पॉप्युलेट करने की अनुमति दी जा सकती है. उदाहरण के लिए, किसी फ़ील्ड को ऐक्सेस करने पर, उस पर टाइमस्टैंप लागू करने के लिए, ऑपरेशन के अनुरोध में सेव किए गए समय का इस्तेमाल किया जा सकता है. updatedAt: Timestamp! @default(expr: "request.time")

Actor और MovieActor टाइप में, कई-से-कई रिलेशनशिप को मैनेज करना

उपयोगकर्ताओं की जानकारी मैनेज करने के बाद, फ़िल्म के डेटा को मॉडल करने पर वापस जाया जा सकता है.

इसके बाद, आपको अपनी फ़िल्मों में कलाकारों को शामिल करना है.

Actor टेबल का स्कीमा बहुत आसान है.

# Actors
# Suppose an actor can participate in multiple movies and movies can have multiple actors
# Movie - Actors (or vice versa) is a many to many relationship
type Actor @table {
  id: UUID! @default(expr: "uuidV4()")
  name: String! @col(dataType: "varchar(30)")
}

अगर आपको कलाकारों को एक से ज़्यादा फ़िल्मों में और फ़िल्मों में एक से ज़्यादा कलाकारों को शामिल करना है, तो आपको "जॉइन टेबल" की ज़रूरत होगी.

MovieActor टेबल, कई-से-कई रिलेशनशिप को मैनेज करती है. इसकी प्राइमरी की, [movie, actor] (movie और actor से फ़ॉरेन की फ़ील्ड) का कॉम्बिनेशन होती है.

# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary keys of this table
# In this case, the keys are [movieId, actorId], the foreign key fields of the reference fields [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
  movie: Movie!
  # movieId: UUID! <- implicitly added foreign key field
  actor: Actor!
  # actorId: UUID! <- implicitly added foreign key field
  role: String! # "main" or "supporting"
  # optional other fields
}

फ़ॉरेन की कंस्ट्रेंट वाली टेबल पर, SQL रिलेशनशिप तय करने पर, SQL Connect दूसरी तरफ़ मौजूद फ़ील्ड को अपने-आप जनरेट करता है. आपको रिवर्स मैपिंग फ़ील्ड (उदाहरण के लिए, Actor से वापस MovieActor) तय करने की ज़रूरत नहीं है.

MovieMetadata टाइप में, एक-से-एक रिलेशनशिप को मैनेज करना

अब, फ़िल्म के डायरेक्टर की जानकारी ट्रैक करें. साथ ही, Movie के साथ एक-से-एक रिलेशनशिप सेट अप करें.

फ़ॉरेन की कंस्ट्रेंट को पसंद के मुताबिक बनाने के लिए, @ref डायरेक्टिव का इस्तेमाल किया जा सकता है:

  • @ref(fields) से यह तय किया जाता है कि किन फ़ॉरेन की फ़ील्ड का इस्तेमाल करना है.
  • @ref(references) से यह तय किया जाता है कि टारगेट टेबल में किन फ़ील्ड का रेफ़रंस देना है. डिफ़ॉल्ट तौर पर, प्राइमरी की का रेफ़रंस दिया जाता है. हालांकि, @unique फ़ील्ड का रेफ़रंस भी दिया जा सकता है. यह एक ज़्यादा बेहतर विकल्प है. SQL Connect अक्सर आपके लिए यह जानकारी अनुमान लगा सकता है.

ज़्यादा जानकारी के लिए, @ref के रेफ़रंस दस्तावेज़ देखें.

# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique ensures that each Movie only has one MovieMetadata.
  movie: Movie! @unique
  # Since it references to another table type, it adds a foreign key constraint.
  #  movie: Movie! @unique @ref(fields: "movieId", references: "id")
  #  movieId: UUID! <- implicitly added foreign key field
  director: String
}

स्कीमा से जनरेट किए गए फ़ील्ड का इस्तेमाल करके, ऑपरेशन बनाना

आपके SQL Connect ऑपरेशन, SQL Connect की ओर से अपने-आप जनरेट किए गए फ़ील्ड के सेट को बढ़ाएंगे. ये फ़ील्ड, आपके स्कीमा में मौजूद टाइप और टाइप रिलेशनशिप के आधार पर जनरेट किए जाते हैं. जब भी स्कीमा में बदलाव किया जाता है, तो ये फ़ील्ड, लोकल टूलिंग की मदद से जनरेट किए जाते हैं.

मान लें कि आपके स्कीमा में Movie टाइप और उससे जुड़ा Actor टाइप शामिल है. SQL Connect जनरेट करता है movie, movies, actors_on_movies फ़ील्ड वगैरह.

`
movie` फ़ील्ड के साथ क्वेरी करना

movie फ़ील्ड, Movie टेबल में मौजूद किसी एक रिकॉर्ड को दिखाता है.

किसी फ़िल्म की की के आधार पर क्वेरी करने के लिए, इस फ़ील्ड का इस्तेमाल करें.

query GetMovie($myKey: Movie_Key!) {
  movie(key: $myKey) { title }
}

`
movies` फ़ील्ड के साथ क्वेरी करना

movies फ़ील्ड, Movie टेबल में मौजूद रिकॉर्ड की सूची को दिखाता है.

एक से ज़्यादा फ़िल्मों के लिए क्वेरी करने के लिए, इस फ़ील्ड का इस्तेमाल करें. उदाहरण के लिए, किसी साल में रिलीज़ हुई सभी फ़िल्मों के लिए क्वेरी की जा सकती है.

query GetMovies($myYear: Int!) {
  movies(where: { year: { eq: $myYear } }) { title }
}


actors_on_movies फ़ील्ड के साथ क्वेरी करना

actors_on_movies फ़ील्ड, रिकॉर्ड की सूची को दिखाता है. यह सूची, Actor और Movie टेबल को कनेक्ट करती है. किसी फ़िल्म से जुड़े सभी कलाकारों के लिए क्वेरी करने के लिए, इस फ़ील्ड का इस्तेमाल करें.

किसी फ़िल्म से जुड़े सभी कलाकारों के लिए क्वेरी करने के लिए, इस फ़ील्ड का इस्तेमाल करें.

  query GetActorsOnMovie($myKey: Movie_Key!) {
    actors_on_movies(where: { movie: { key: { eq: $myKey } } }) {
      actor { name }
    }
  }

इसे ध्यान में रखते हुए, इन फ़ील्ड का इस्तेमाल करके ऑपरेशन लागू करने का तरीका पढ़ा जा सकता है क्वेरी लागू करने के बारे में गाइड और म्यूटेशन लागू करने के बारे में गाइड में.

स्कीमा के ज़्यादा बेहतर कॉन्सेप्ट

इन्यूमरेटेड फ़ील्ड

SQL Connect इन्यूमरेटेड फ़ील्ड को सपोर्ट करता है. ये फ़ील्ड, PostgreSQL के इन्यूमरेटेड टाइप से मैप होते हैं. इनम की मदद से, किसी खास क्रम में, पहले से तय की गई स्टैटिक वैल्यू की सूची को तेज़ी से तय किया जा सकता है.

अपने स्कीमा में इनम जोड़ने के लिए, इनम और उसकी पहले से तय की गई वैल्यू का एलान करें. इसके बाद, अपने टाइप में उसका रेफ़रंस दें.

enum AspectRatio {
   ACADEMY
   WIDESCREEN
   ANAMORPHIC
   IMAX
   "No information available on aspect ratio"
   UNAVAILABLE
}

type Movie
  @table {
  title: String! 
  genre: String
  description: String
  originalAspectRatio: AspectRatio! @default(value: WIDESCREEN)
  otherAspectRatios: [AspectRatio!]
  tags: [String]
  rating: Float
  imageUrl: String!
  releaseYear: Int
}

Movie टाइप में, हमने originalAspectRatio नाम का एक इनम फ़ील्ड जोड़ा है. यह फ़ील्ड, उस पहलू के अनुपात को दिखाता है जिसमें फ़िल्म शूट की गई थी. इसके अलावा, otherAspectRatios नाम का एक और फ़ील्ड जोड़ा गया है. यह फ़ील्ड, उपलब्ध अन्य पहलू के अनुपातों की सूची को दिखाता है.

इन्यूमरेटेड फ़ील्ड में किए गए बदलावों को मैनेज करना

अपने इनम में नई वैल्यू जोड़ी जा सकती हैं. हालांकि, इनम सूची का क्रम बहुत अहम होता है. इसलिए, नई वैल्यू को सोच-समझकर जोड़ें. किसी इनम में, पूरी तरह से बैकवर्ड-कम्पैटिबल बदलाव सिर्फ़ तब किया जा सकता है, जब वैल्यू की सूची के आखिर में कोई नई वैल्यू जोड़ी जाए. खास तौर पर, पहले से पब्लिश किए गए इनम के बीच कोई नई वैल्यू जोड़ने या मौजूदा वैल्यू का क्रम बदलने पर, क्वेरी में "से कम" जैसे रिलेटिव ऑपरेटर का इस्तेमाल करने पर, रिलेटिव क्रम बदल जाता है. वैल्यू को हटाने या उनका नाम बदलने पर, हमेशा बैकवर्ड-इनकम्पैटिबल बदलाव होता है.

इनम वैल्यू की सूची में मौजूद वैल्यू का क्रम कभी नहीं बदलना चाहिए. क्रम अहम होता है, क्योंकि इससे फ़िल्टरिंग लागू करने का तरीका बदल जाता है.

इनम वैल्यू में बदलाव करते समय सावधानी बरतनी चाहिए, ताकि आपके ऑपरेशन या क्लाइंट कोड के पुराने वर्शन पर कोई असर न पड़े. किसी इनम वैल्यू को हटाते या उसका नाम बदलते समय, पक्का करें कि आपके मौजूदा डेटाबेस में उसकी कोई अन्य इंस्टेंस मौजूद न हो.

ऑपरेशन और क्लाइंट कोड में, अपने इनम फ़ील्ड का इस्तेमाल करना

स्कीमा में इनम फ़ील्ड जोड़ने के बाद, इस फ़ील्ड का इस्तेमाल क्वेरी और क्लाइंट कोड में किया जा सकता है.

क्वेरी गाइड में, इनम का इस्तेमाल करके क्वेरी लिखने के बारे में ज़्यादा जानें. साथ ही, यह भी जानें कि क्लाइंट को कैसे लिखा जाए, ताकि क्वेरी में आपके इनम में बदलाव किए जा सकें.

अन्य बेहतर कॉन्सेप्ट

बुनियादी, लेकिन काम के टाइप और रिलेशनशिप के अलावा अन्य टाइप और रिलेशनशिप के बारे में जानने के लिए, रेफ़रंस दस्तावेज़ में दिए गए उदाहरण देखें.

डेटा टाइप, जो इस्तेमाल किए जा सकते हैं

SQL Connect इन स्केलर डेटा टाइप को सपोर्ट करता है. साथ ही, का इस्तेमाल करके, इन्हें PostgreSQL टाइप असाइन किया जा सकता है.@col(dataType:)

SQL Connect टाइप GraphQL का इन-बिल्ट टाइप या
SQL Connect कस्टम टाइप
डिफ़ॉल्ट PostgreSQL टाइप PostgreSQL के ऐसे टाइप जिन्हें इस्तेमाल किया जा सकता है
(कोष्ठक में एलियास)
स्ट्रिंग GraphQL टेक्स्ट टेक्स्ट
bit(n), varbit(n)
char(n), varchar(n)
Int GraphQL int Int2 (smallint, smallserial),
int4 (integer, int, serial)
फ़्लोट GraphQL float8 float4 (real)
float8 (double precision)
numeric (decimal)
बूलियन GraphQL बूलियन बूलियन
यूयूआईडी कस्टम uuid uuid
Int64 कस्टम bigint int8 (bigint, bigserial)
numeric (decimal)
तारीख कस्टम तारीख तारीख
टाइमस्टैम्प कस्टम timestamptz

timestamptz

ध्यान दें: स्थानीय टाइमज़ोन की जानकारी सेव नहीं की जाती.
PostgreSQL, ऐसे टाइमस्टैंप को यूटीसी में बदलता है और सेव करता है.

इन्यूमरेटेड कस्टम enum

enum

वेक्टर कस्टम वेक्टर

वेक्टर

Vertex AI की मदद से, वेक्टर सिमिलैरिटी सर्च करने का तरीका देखें.

  • GraphQL List, एक डाइमेंशन वाले कलेक्शन से मैप होता है.
    • उदाहरण के लिए, [Int], int5[] से मैप होता है. वहीं, [Any], jsonb[] से मैप होता है.
    • SQL Connect नेस्ट किए गए कलेक्शन को सपोर्ट नहीं करता.

SQL स्कीमा

-- Movies Table
CREATE TABLE Movies (
    movie_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    release_year INT,
    genre VARCHAR(30),
    rating INT,
    description TEXT,
    tags TEXT[]
);
-- Movie Metadata Table
CREATE TABLE MovieMetadata (
    movie_id UUID REFERENCES Movies(movie_id) UNIQUE,
    director VARCHAR(255) NOT NULL,
    PRIMARY KEY (movie_id)
);
-- Actors Table
CREATE TABLE Actors (
    actor_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    name VARCHAR(30) NOT NULL
);
-- MovieActor Join Table for Many-to-Many Relationship
CREATE TABLE MovieActor (
    movie_id UUID REFERENCES Movies(movie_id),
    actor_id UUID REFERENCES Actors(actor_id),
    role VARCHAR(50) NOT NULL, # "main" or "supporting"
    PRIMARY KEY (movie_id, actor_id),
    FOREIGN KEY (movie_id) REFERENCES Movies(movie_id),
    FOREIGN KEY (actor_id) REFERENCES Actors(actor_id)
);
-- Users Table
CREATE TABLE Users (
    user_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    user_auth VARCHAR(255) NOT NULL
    username VARCHAR(30) NOT NULL
);
-- Reviews Table
CREATE TABLE Reviews (
    review_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    user_id UUID REFERENCES Users(user_id),
    movie_id UUID REFERENCES Movies(movie_id),
    rating INT,
    review_text TEXT,
    review_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE (movie_id, user_id)
    FOREIGN KEY (user_id) REFERENCES Users(user_id),
    FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
-- Self Join Example for Movie Sequel Relationship
ALTER TABLE Movies
ADD COLUMN sequel_to UUID REFERENCES Movies(movie_id);

अगले चरण

इन विषयों में आपकी दिलचस्पी हो सकती है: