Data Connect के स्कीमा, क्वेरी, और म्यूटेशन

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

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

इस गाइड में, स्कीमा के उदाहरणों के साथ Data Connect क्वेरी और म्यूटेशन को जोड़ा गया है. Data Connect स्कीमा के बारे में बताने वाली गाइड में, क्वेरी (और म्यूटेशन) के बारे में क्यों चर्चा की गई है? GraphQL पर आधारित अन्य प्लैटफ़ॉर्म की तरह ही, Firebase Data Connect एक क्वेरी-फ़र्स्ट डेवलपमेंट प्लैटफ़ॉर्म है. इसलिए, डेवलपर के तौर पर, आपको डेटा मॉडलिंग में अपने क्लाइंट के ज़रूरी डेटा के बारे में सोचना होगा. इससे, आपके प्रोजेक्ट के लिए डेटा स्कीमा पर काफ़ी असर पड़ेगा.

इस गाइड में, फ़िल्म की समीक्षाओं के लिए नए स्कीमा के बारे में बताया गया है. इसके बाद, उस स्कीमा से मिली क्वेरी और म्यूटेशन के बारे में बताया गया है. आखिर में, मुख्य Data Connect स्कीमा के बराबर की एसक्यूएल लिस्टिंग दी गई है.

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

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

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

मूवी टेबल

फ़िल्मों के स्कीमा में मुख्य निर्देश शामिल होते हैं, जैसे:

  • @table, जिसकी मदद से singular और plural आर्ग्युमेंट का इस्तेमाल करके, ऑपरेशन के नाम सेट किए जा सकते हैं
  • कॉलम के नाम साफ़ तौर पर सेट करने के लिए @col
  • @default को डिफ़ॉल्ट सेटिंग सेट करने की अनुमति दें.
# Movies
type Movie
  @table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
  id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
  title: String!
  releaseYear: Int @col(name: "release_year")
  genre: String
  rating: Int @col(name: "rating")
  description: String @col(name: "description")
}

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

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

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

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

मूवी का मेटाडेटा टेबल

अब फ़िल्म के निर्देशकों का ट्रैक रखते हैं. साथ ही, Movie के साथ एक-एक करके संबंध सेट अप करते हैं.

संबंधों की जानकारी देने के लिए, @ref डायरेक्टिव जोड़ें.

# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
  @table(
    name: "MovieMetadata"
  ) {
  # @ref creates a field in the current table (MovieMetadata) that holds the
  # primary key of the referenced type
  # In this case, @ref(fields: "id") is implied
  movie: Movie! @ref
  # movieId: UUID <- this is created by the above @ref
  director: String @col(name: "director")
}

Actor और MovieActor

इसके बाद, आपको अपनी फ़िल्मों में कलाकारों को कास्ट करना है. फ़िल्मों और कलाकारों के बीच कई-से-कई संबंध होने की वजह से, जॉइन टेबल बनाएं.

# 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(name: "Actors", singular: "actor", plural: "actors") {
  id: UUID! @col(name: "actor_id") @default(expr: "uuidV4()")
  name: String! @col(name: "name", dataType: "varchar(30)")
}
# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary key(s) of this table
# In this case, the keys are [movieId, actorId], the generated fields of the reference types [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
  # @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type
  # In this case, @ref(fields: "id") is implied
  movie: Movie! @ref
  # movieId: UUID! <- this is created by the above @ref, see: implicit.gql
  actor: Actor! @ref
  # actorId: UUID! <- this is created by the above @ref, see: implicit.gql
  role: String! @col(name: "role") # "main" or "supporting"
  # optional other fields
}

उपयोगकर्ता

आखिर में, आपके ऐप्लिकेशन के उपयोगकर्ता.

# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship, movie:reviews is a one to many relationship, movie:user is a many to many relationship
type User
  @table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
  id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
  auth: String @col(name: "user_auth") @default(expr: "auth.uid")
  username: String! @col(name: "username", dataType: "varchar(30)")
  # The following are generated from the @ref in the Review table
  # reviews_on_user
  # movies_via_Review
}

ऐसे डेटा टाइप जिन्हें PostgreSQL में प्रोसेस किया जा सकता है

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

Data Connect टाइप GraphQL में पहले से मौजूद टाइप या
Data 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 (रीयल)
float8 (डबल प्रिसिज़न)
numeric (डेसीमल)
बूलियन GraphQL बूलियन बूलियन
यूयूआईडी कस्टम uuid यूयूआईडी
Int64 कस्टम bigint int8 (bigint, bigserial)
numeric (decimal)
तारीख कस्टम date तारीख
टाइमस्टैंप कस्टम timestamptz

timestamptz

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

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

वेक्टर

Vertex AI की मदद से, वेक्टर की मिलती-जुलती वैल्यू खोजने की सुविधा देखें.

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

इंप्लिसिट और पहले से तय क्वेरी और म्यूटेशन

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

डेवलपमेंट की प्रोसेस में, आपको इन इंप्लिसिट ऑपरेशन के आधार पर, पहले से तय क्वेरी और पहले से तय म्यूटेशन लागू करने होंगे.

इंप्लिसिट क्वेरी और म्यूटेशन का नाम देना

Data Connect, आपके स्कीमा टाइप के एलान से, इनपुट के तौर पर इस्तेमाल होने वाली क्वेरी और म्यूटेशन के लिए सही नामों का अनुमान लगाता है. उदाहरण के लिए, PostgreSQL के सोर्स का इस्तेमाल करते समय, अगर आपने Movie नाम की कोई टेबल तय की है, तो सर्वर इनपुट के तौर पर ये जनरेट करेगा:

  • एक टेबल के इस्तेमाल के उदाहरणों के लिए क्वेरी, जिनके नाम आसान हैं. जैसे, movie (एकवचन, eq जैसे आर्ग्युमेंट पास करके अलग-अलग नतीजे पाने के लिए) और movies (बहुवचन, gt जैसे आर्ग्युमेंट और orderby जैसे ऑपरेशन पास करके नतीजों की सूचियां पाने के लिए). Data Connect, कई टेबल के लिए क्वेरी भी जनरेट करता है. ये क्वेरी, actors_on_movies या actors_via_actormovie जैसे साफ़ तौर पर बताए गए नामों के साथ रिलेशनल ऑपरेशन करती हैं.
  • movie_insert, movie_upsert नाम वाले म्यूटेशन...

स्कीमा डेफ़िनिशन लैंग्वेज की मदद से, singular और plural डायरेक्टिव आर्ग्युमेंट का इस्तेमाल करके, ऑपरेशन के लिए नाम भी साफ़ तौर पर सेट किए जा सकते हैं.

क्वेरी और म्यूटेशन के लिए निर्देश

टाइप और टेबल तय करने के लिए इस्तेमाल किए जाने वाले डायरेक्टिव के अलावा, Data Connect में क्वेरी और म्यूटेशन के व्यवहार को बेहतर बनाने के लिए, @auth, @check, @redact, और @transaction डायरेक्टिव भी उपलब्ध हैं.

निर्देश इन पर लागू होता है ब्यौरा
@auth क्वेरी और म्यूटेशन किसी क्वेरी या म्यूटेशन के लिए पुष्टि करने की नीति तय करता है. अनुमति और पुष्टि करने की गाइड देखें.
@check अनुमति के डेटा के लिए लुकअप क्वेरी यह पुष्टि करता है कि क्वेरी के नतीजों में बताए गए फ़ील्ड मौजूद हैं. फ़ील्ड वैल्यू की जांच करने के लिए, कॉमन एक्सप्रेशन लैंग्वेज (सीईएल) एक्सप्रेशन का इस्तेमाल किया जाता है. अनुमति और पुष्टि करने की गाइड देखें.
@redact क्वेरी क्लाइंट के जवाब के किसी हिस्से को छिपाता है. अनुमति और पुष्टि करने की गाइड देखें.
@transaction म्यूटेशन यह पक्का करता है कि कोई म्यूटेशन हमेशा डेटाबेस ट्रांज़ैक्शन में चलता है. मूवी ऐप्लिकेशन में बदलाव करने के उदाहरण देखें.

फ़िल्म की समीक्षा के डेटाबेस के लिए क्वेरी

Data Connect क्वेरी को क्वेरी ऑपरेशन टाइप के एलान, ऑपरेशन के नाम, शून्य या उससे ज़्यादा ऑपरेशन आर्ग्युमेंट, और आर्ग्युमेंट के साथ शून्य या उससे ज़्यादा निर्देशों के साथ तय किया जाता है.

क्वेरी बनाने के लिए ज़रूरी जानकारी वाले सेक्शन में, listEmails क्वेरी के उदाहरण में कोई पैरामीटर नहीं दिया गया है. हालांकि, कई मामलों में क्वेरी फ़ील्ड में भेजा गया डेटा डाइनैमिक होगा. क्वेरी डेफ़िनिशन के कॉम्पोनेंट के तौर पर वैरिएबल के साथ काम करने के लिए, $variableName सिंटैक्स का इस्तेमाल किया जा सकता है.

इसलिए, इस क्वेरी में:

  • query टाइप की परिभाषा
  • ListMoviesByGenre ऑपरेशन (क्वेरी) का नाम
  • एक वैरिएबल $genre ऑपरेशन आर्ग्युमेंट
  • एक डायरेक्टिव, @auth.
query ListMoviesByGenre($genre: String!) @auth(level: USER)

हर क्वेरी आर्ग्युमेंट के लिए, टाइप का एलान करना ज़रूरी है. यह String जैसा पहले से मौजूद हो सकता है या Movie जैसा स्कीमा से तय किया गया कस्टम टाइप हो सकता है.

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

क्वेरी में मुख्य स्केलर

हालांकि, सबसे पहले मुख्य स्केलर के बारे में जानकारी दें.

Data Connect, मुख्य स्केलर के लिए एक खास टाइप तय करता है, जिसकी पहचान _Key से की जाती है. उदाहरण के लिए, हमारी Movie टेबल के लिए, मुख्य स्केलर का टाइप Movie_Key है.

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

हमारे मौजूदा उदाहरण में movie जैसी सिंगल ऑटोमैटिक क्वेरी, एक मुख्य आर्ग्युमेंट के साथ काम करती हैं. यह आर्ग्युमेंट, मुख्य स्केलर स्वीकार करता है.

किसी कीवर्ड स्केलर को लिटरल के तौर पर पास किया जा सकता है. हालांकि, इनपुट के तौर पर मुख्य स्केलर पास करने के लिए, वैरिएबल तय किए जा सकते हैं.

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

इन्हें अनुरोध के JSON फ़ॉर्मैट में इस तरह या सीरियलाइज़ेशन के अन्य फ़ॉर्मैट में दिया जा सकता है:

{
  # 
  "variables": {
    "myKey": {"foo": "some-string-value", "bar": 42}
  }
}

कस्टम स्केलर पार्सिंग की मदद से, ऑब्जेक्ट सिंटैक्स का इस्तेमाल करके भी Movie_Key बनाया जा सकता है. इसमें वैरिएबल हो सकते हैं. यह सुविधा तब ज़्यादा काम की होती है, जब आपको किसी वजह से अलग-अलग कॉम्पोनेंट को अलग-अलग वैरिएबल में बांटना हो.

क्वेरी में बदलाव करना

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

यहां एक क्वेरी दी गई है, जिसमें एक्सप्रेशन में mostPopular का इस्तेमाल किया गया है.

query ReviewTopPopularity($genre: String) {
  mostPopular: review(first: {
    where: {genre: {eq: $genre}},
    orderBy: {popularity: DESC}
  }) {  }
}

फ़िल्टर की मदद से आसान क्वेरी बनाना

Data Connect क्वेरी, सभी सामान्य SQL फ़िल्टर और ऑर्डर ऑपरेशन से मैप होती हैं.

where और orderBy ऑपरेटर (एकवचन, बहुवचन क्वेरी)

टेबल और नेस्ट किए गए असोसिएशन से मैच होने वाली सभी पंक्तियां दिखाता है. अगर कोई रिकॉर्ड फ़िल्टर से मैच नहीं करता है, तो यह एक खाली कलेक्शन दिखाता है.

query MovieByTopRating($genre: String) {
  mostPopular: movies(
     where: { genre: { eq: $genre } }, orderBy: { rating: DESC }
  ) {
    # graphql: list the fields from the results to return
    id
    title
    genre
    description
  }
}

query MoviesByReleaseYear($min: Int, $max: Int) {
  movies(where: {releaseYear: {le: $max, ge: $min}}, orderBy: [{releaseYear: ASC}]) {  }
}

limit और offset ऑपरेटर (एकवचन, बहुवचन क्वेरी)

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

query MoviesTop10 {
  movies(orderBy: [{ rating: DESC }], limit: 10) {
    # graphql: list the fields from the results to return
    title
  }
}

includes for array fields

यह जांच की जा सकती है कि किसी ऐरे फ़ील्ड में कोई खास आइटम शामिल है या नहीं.

# Filter using arrays and embedded fields.
query ListMoviesByTag($tag: String!) {
  movies(where: { tags: { includes: $tag }}) {
    # graphql: list the fields from the results to return
    id
    title
  }
}

स्ट्रिंग ऑपरेशन और रेगुलर एक्सप्रेशन

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

query MoviesTitleSearch($prefix: String, $suffix: String, $contained: String, $regex: String) {
  prefixed: movies(where: {title: {startsWith: $prefix}}) {...}
  suffixed: movies(where: {title: {endsWith: $suffix}}) {...}
  contained: movies(where: {title: {contains: $contained}}) {...}
  matchRegex: movies(where: {title: {pattern: {regex: $regex}}}) {...}
}

कंपोज किए गए फ़िल्टर के लिए or और and

ज़्यादा जटिल लॉजिक के लिए, or और and का इस्तेमाल करें.

query ListMoviesByGenreAndGenre($minRating: Int!, $genre: String) {
  movies(
    where: { _or: [{ rating: { ge: $minRating } }, { genre: { eq: $genre } }] }
  ) {
    # graphql: list the fields from the results to return
    title
  }
}

Complex क्वेरी

Data Connect क्वेरी, टेबल के बीच के संबंधों के आधार पर डेटा ऐक्सेस कर सकती हैं. नेस्ट की गई क्वेरी बनाने के लिए, अपने स्कीमा में तय किए गए ऑब्जेक्ट (वन-टू-वन) या कलेक्शन (वन-टू-मेनी) रिलेशनशिप का इस्तेमाल किया जा सकता है. इसका मतलब है कि नेस्ट किए गए या मिलते-जुलते टाइप के डेटा के साथ-साथ, एक टाइप का डेटा भी फ़ेच किया जा सकता है.

ऐसी क्वेरी, जनरेट की गई इनपुट क्वेरी में मैजिक Data Connect _on_ और _via सिंटैक्स का इस्तेमाल करती हैं.

आपको हमारे शुरुआती वर्शन के स्कीमा में बदलाव करने होंगे.

कई से एक

आइए, अपने ऐप्लिकेशन में समीक्षाएं जोड़ते हैं. इसके लिए, Review टेबल और User में बदलाव करें.

# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship,
# movie:reviews is a one to many relationship,
# movie:user is a many to many relationship
type User
  @table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
  id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
  auth: String @col(name: "user_auth") @default(expr: "auth.uid")
  username: String! @col(name: "username", dataType: "varchar(30)")
  # The following are generated from the @ref in the Review table
  # reviews_on_user
  # movies_via_Review
}
# Reviews
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  id: UUID! @col(name: "review_id") @default(expr: "uuidV4()")
  user: User! @ref
  movie: Movie! @ref
  rating: Int
  reviewText: String
  reviewDate: Date! @default(expr: "request.time")
}

कई-एक के लिए क्वेरी

अब _via_ सिंटैक्स को समझने के लिए, किसी ऐसी क्वेरी पर नज़र डालें जिसमें अलग नाम दिया गया हो.

query UserMoviePreferences($username: String!) @auth(level: USER) {
  users(where: { username: { eq: $username } }) {
    likedMovies: movies_via_review(where: { rating: { ge: 4 } }) {
      title
      genre
      description
    }
    dislikedMovies: movies_via_review(where: { rating: { le: 2 } }) {
      title
      genre
      description
    }
  }
}

वन-टू-वन

आपको पैटर्न दिख सकता है. उदाहरण के लिए, नीचे स्कीमा में बदलाव किया गया है.

# Movies
type Movie
  @table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
  id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
  title: String!
  releaseYear: Int @col(name: "release_year")
  genre: String
  rating: Int @col(name: "rating")
  description: String @col(name: "description")
  tags: [String] @col(name: "tags")
}
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
  @table(
    name: "MovieMetadata"
  ) {
  # @ref creates a field in the current table (MovieMetadata) that holds the primary key of the referenced type
  # In this case, @ref(fields: "id") is implied
  movie: Movie! @ref
  # movieId: UUID <- this is created by the above @ref
  director: String @col(name: "director")
}


extend type MovieMetadata {
  movieId: UUID! # matches primary key of referenced type
...
}

extend type Movie {
  movieMetadata: MovieMetadata # can only be non-nullable on ref side
  # conflict-free name, always generated
  movieMetadatas_on_movie: MovieMetadata
}

वन-टू-वन कॉल के लिए क्वेरी

_on_ सिंटैक्स का इस्तेमाल करके क्वेरी की जा सकती है.

# One to one
query GetMovieMetadata($id: UUID!) @auth(level: PUBLIC) {
  movie(id: $id) {
    movieMetadatas_on_movie {
      director
    }
  }
}

कई-से-कई

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

# MovieActors Join Table Definition
type MovieActors @table(
  key: ["movie", "actor"] # join key triggers many-to-many generation
) {
  movie: Movie!
  actor: Actor!
}

# generated extensions for the MovieActors join table
extend type MovieActors {
  movieId: UUID!
  actorId: UUID!
}

# Extensions for Actor and Movie to handle many-to-many relationships
extend type Movie {
  movieActors: [MovieActors!]! # standard many-to-one relation to join table
  actors: [Actor!]! # many-to-many via join table

  movieActors_on_actor: [MovieActors!]!
  # since MovieActors joins distinct types, type name alone is sufficiently precise
  actors_via_MovieActors: [Actor!]!
}

extend type Actor {
  movieActors: [MovieActors!]! # standard many-to-one relation to join table
  movies: [Movie!]! # many-to-many via join table

  movieActors_on_movie: [MovieActors!]!
  movies_via_MovieActors: [Movie!]!
}

कई-से-कई के लिए क्वेरी

_via_ सिंटैक्स को समझने के लिए, किसी ऐसी क्वेरी पर नज़र डालें जिसमें किसी एलिमेंट को अलग नाम दिया गया हो.

query GetMovieCast($movieId: UUID!, $actorId: UUID!) @auth(level: PUBLIC) {
  movie(id: $movieId) {
    mainActors: actors_via_MovieActor(where: { role: { eq: "main" } }) {
      name
    }
    supportingActors: actors_via_MovieActor(
      where: { role: { eq: "supporting" } }
    ) {
      name
    }
  }
  actor(id: $actorId) {
    mainRoles: movies_via_MovieActor(where: { role: { eq: "main" } }) {
      title
    }
    supportingRoles: movies_via_MovieActor(
      where: { role: { eq: "supporting" } }
    ) {
      title
    }
  }
}

फ़िल्म की समीक्षा के डेटाबेस के लिए म्यूटेशन

जैसा कि बताया गया है, अपने स्कीमा में टेबल तय करने पर, Data Connect हर टेबल के लिए बुनियादी इंप्लिसिट म्यूटेशन जनरेट करेगा.

type Movie @table { ... }

extend type Mutation {
  # Insert a row into the movie table.
  movie_insert(...): Movie_Key!
  # Upsert a row into movie."
  movie_upsert(...): Movie_Key!
  # Update a row in Movie. Returns null if a row with the specified id/key does not exist
  movie_update(...): Movie_Key
  # Update rows based on a filter in Movie.
  movie_updateMany(...): Int!
  # Delete a single row in Movie. Returns null if a row with the specified id/key does not exist
  movie_delete(...): Movie_Key
  # Delete rows based on a filter in Movie.
  movie_deleteMany(...): Int!
}

इनकी मदद से, CRUD के ज़्यादा जटिल कोर केस लागू किए जा सकते हैं. इसे तेज़ी से पांच बार बोलें!

@transaction डायरेक्टिव

यह डायरेक्टिव यह लागू करता है कि कोई म्यूटेशन हमेशा डेटाबेस लेन-देन में चलता है.

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

@transaction के बिना म्यूटेशन, हर रूट फ़ील्ड को क्रम में एक के बाद एक लागू करते हैं. यह किसी भी गड़बड़ी को फ़ील्ड में हुई गड़बड़ी के तौर पर दिखाता है. हालांकि, बाद में होने वाली गड़बड़ियों का असर नहीं दिखाता.

बनाएं

आइए, बुनियादी क्रिएट करते हैं.

# Create a movie based on user input
mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
  movie_insert(data: {
    title: $title
    releaseYear: $releaseYear
    genre: $genre
    rating: $rating
  })
}

# Create a movie with default values
mutation CreateMovie2 {
  movie_insert(data: {
    title: "Sherlock Holmes"
    releaseYear: 2009
    genre: "Mystery"
    rating: 5
  })
}

या अप्सर्ट.

# Movie upsert using combination of variables and literals
mutation UpsertMovie($title: String!) {
  movie_upsert(data: {
    title: $title
    releaseYear: 2009
    genre: "Mystery"
    rating: 5
    genre: "Mystery/Thriller"
  })
}

अपडेट करना

यहां अपडेट दिए गए हैं. प्रोड्यूसर और डायरेक्टर्स को उम्मीद होती है कि औसत रेटिंग अच्छी हो.

mutation UpdateMovie(
  $id: UUID!,
  $genre: String!,
  $rating: Int!,
  $description: String!
) {
  movie_update(id: $id, data: {
    genre: $genre
    rating: $rating
    description: $description
  })
}

# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $ratingIncrement: Int!) {
  movie_updateMany(
    where: { genre: { eq: $genre } },
    update: { rating: { inc: $ratingIncrement } }
  )
}

मिटाना

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

# Delete by key
mutation DeleteMovie($id: UUID!) {
  movie_delete(id: $id)
}

यहां _deleteMany का इस्तेमाल किया जा सकता है.

# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
  movie_deleteMany(where: { rating: { le: $minRating } })
}

रिलेशन पर म्यूटेशन लिखना

किसी संबंध पर, इंप्लिसिट _upsert म्यूटेशन का इस्तेमाल करने का तरीका जानें.

# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
  movieMetadata_upsert(
    data: { movie: { id: $movieId }, director: $director }
  )
}

अनुमति के डेटा के लिए लुकअप क्वेरी

Data Connect डेटाबेस में बदलाव करने की अनुमति पाने के लिए, सबसे पहले डेटाबेस से क्वेरी की जानी चाहिए. इसके बाद, CEL एक्सप्रेशन की मदद से क्वेरी के नतीजों की पुष्टि की जानी चाहिए. यह तब काम आता है, जब किसी टेबल में लिखते समय आपको किसी दूसरी टेबल की पंक्ति का कॉन्टेंट देखना हो.

यह सुविधा इनके साथ काम करती है:

  • @check डायरेक्टिव, जिसकी मदद से फ़ील्ड के कॉन्टेंट का आकलन किया जा सकता है. साथ ही, इस आकलन के नतीजों के आधार पर:
    • म्यूटेशन के हिसाब से, बनाने, अपडेट करने, और मिटाने की प्रोसेस जारी रखें
    • अपने क्लाइंट में अलग-अलग लॉजिक लागू करने के लिए, क्वेरी से क्लाइंट को मिली वैल्यू का इस्तेमाल करें
  • @redact डायरेक्टिव, जिसकी मदद से वायर प्रोटोकॉल के नतीजों से क्वेरी के नतीजे हटाए जा सकते हैं.

ये सुविधाएं, अनुमति फ़्लो के लिए काम की हैं.

मिलता-जुलता एसक्यूएल स्कीमा

-- 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);

आगे क्या करना है?