طرحواره ها، پرس و جوها و جهش های اتصال داده

Firebase Data Connect به شما امکان می دهد برای نمونه های PostgreSQL خود که با Google Cloud SQL مدیریت می شوند، رابط ایجاد کنید. این رابط‌ها ترکیبی از طرح‌واره، پرسش‌ها و جهش‌ها برای استفاده از داده‌های شما هستند.

راهنمای شروع یک طرح برنامه بررسی فیلم را برای PostgreSQL معرفی کرد و این راهنما نگاهی عمیق تر به نحوه طراحی طرحواره های Data Connect برای PostgreSQL دارد.

این راهنما پرس و جوها و جهش های Data Connect را با نمونه های طرحواره جفت می کند. چرا پرس و جوهاجهش ها ) را در راهنمای طرحواره های Data Connect مورد بحث قرار می دهیم؟ مانند سایر پلتفرم‌های مبتنی بر GraphQL، Firebase Data Connect یک پلتفرم توسعه اولین پرس و جو است، بنابراین به‌عنوان یک توسعه‌دهنده، در مدل‌سازی داده‌های خود به داده‌هایی فکر می‌کنید که مشتریانتان به آن نیاز دارند، که تا حد زیادی بر طرح داده‌ای که برای خود ایجاد می‌کنید، تأثیر می‌گذارد. پروژه

این راهنما با طرحی جدید برای بررسی فیلم شروع می‌شود، سپس پرسش‌ها و جهش‌های حاصل از آن طرح را پوشش می‌دهد و در نهایت فهرستی از SQL معادل طرح اصلی 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")
}

بازیگر و بازیگر سینما

در مرحله بعد، شما می خواهید بازیگران در فیلم های شما بازی کنند، و از آنجایی که بین فیلم ها و بازیگران رابطه چند به چند دارید، یک جدول پیوستن ایجاد کنید.

# 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
}

انواع داده های پشتیبانی شده

Data Connect از انواع داده های اسکالر زیر پشتیبانی می کند، با انتساب به انواع PostgreSQL با استفاده از @col(dataType:) .

نوع Data Connect GraphQL توکار نوع یا
نوع سفارشی Data Connect
نوع پیش فرض PostgreSQL پشتیبانی از انواع PostgreSQL
(نام مستعار داخل پرانتز)
رشته GraphQL متن متن
بیت (n)، varbit (n)
char(n)، varchar(n)
بین المللی GraphQL بین المللی Int2 (کوچک، سریال کوچک)،
int4 (عدد صحیح، int، سریال)
شناور GraphQL شناور8 float4 (واقعی)
float8 (دقت دوگانه)
عددی (اعشاری)
بولی GraphQL بولی بولی
UUID سفارشی uuid uuid
Int64 سفارشی bigint int8 (bigint، bigserial)
عددی (اعشاری)
تاریخ سفارشی تاریخ تاریخ
مهر زمان سفارشی timestamptz

timestamptz

توجه: اطلاعات منطقه زمانی محلی ذخیره نمی شود.
PostgreSQL مُهرهای زمانی مانند UTC را تبدیل و ذخیره می کند.

بردار سفارشی بردار

بردار

به انجام جستجوی شباهت برداری با 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 درخواست جستجوی داده های مجوز بررسی می کند که فیلدهای مشخص شده در نتایج پرس و جو وجود دارد. یک عبارت Common Expression Language (CEL) برای آزمایش مقادیر فیلد استفاده می شود. راهنمای مجوز و گواهینامه را ببینید.
@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
  }
}

شامل زمینه های آرایه می شود

می توانید آزمایش کنید که یک فیلد آرایه شامل یک آیتم مشخص شده باشد.

# 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
  }
}

پرس و جوهای پیچیده

کوئری های Data Connect می توانند به داده ها بر اساس روابط بین جداول دسترسی داشته باشند. شما می توانید از روابط شی (یک به یک) یا آرایه (یک به چند) تعریف شده در طرحواره خود برای ایجاد پرس و جوهای تودرتو، یعنی واکشی داده برای یک نوع به همراه داده های یک نوع تودرتو یا مرتبط استفاده کنید.

چنین پرس و جوهایی از جادویی Data Connect _on_ و _via syntax در جستارهای ضمنی تولید شده استفاده می کنند.

شما تغییراتی در طرحواره از نسخه اولیه ما ایجاد خواهید کرد.

بسیاری به یک

بیایید نظرات را به برنامه خود اضافه کنیم، با جدول 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 ، که به شما امکان می دهد نتایج پرس و جو را از نتایج پروتکل سیمی حذف کنید.

این ویژگی ها برای جریان های مجوز مفید هستند.

طرحواره 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);

بعدش چی؟

  • بیاموزید که چگونه پرس و جوها و جهش های خود را با مجوز و گواهی ایمن کنید.
  • با نحوه فراخوانی پرسش‌ها و جهش‌های خود از یک وب SDK ، Android SDK ، iOS SDK و Flutter SDK که به‌طور خودکار ایجاد می‌شود، بیاموزید.
،

Firebase Data Connect به شما امکان می دهد برای نمونه های PostgreSQL خود که با Google Cloud SQL مدیریت می شوند، رابط ایجاد کنید. این رابط‌ها ترکیبی از طرح‌واره، پرسش‌ها و جهش‌ها برای استفاده از داده‌های شما هستند.

راهنمای شروع یک طرح برنامه بررسی فیلم را برای PostgreSQL معرفی کرد و این راهنما نگاهی عمیق تر به نحوه طراحی طرحواره های Data Connect برای PostgreSQL دارد.

این راهنما پرس و جوها و جهش های Data Connect را با نمونه های طرحواره جفت می کند. چرا پرس و جوهاجهش ها ) را در راهنمای طرحواره های Data Connect مورد بحث قرار می دهیم؟ مانند سایر پلتفرم‌های مبتنی بر GraphQL، Firebase Data Connect یک پلتفرم توسعه اولین پرس و جو است، بنابراین به‌عنوان یک توسعه‌دهنده، در مدل‌سازی داده‌های خود به داده‌هایی فکر می‌کنید که مشتریانتان به آن نیاز دارند، که تا حد زیادی بر طرح داده‌ای که برای خود ایجاد می‌کنید، تأثیر می‌گذارد. پروژه

این راهنما با طرحی جدید برای بررسی فیلم شروع می‌شود، سپس پرسش‌ها و جهش‌های حاصل از آن طرح را پوشش می‌دهد و در نهایت فهرستی از SQL معادل طرح اصلی 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")
}

بازیگر و بازیگر سینما

در مرحله بعد، شما می خواهید بازیگران در فیلم های شما بازی کنند، و از آنجایی که بین فیلم ها و بازیگران رابطه چند به چند دارید، یک جدول پیوستن ایجاد کنید.

# 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
}

انواع داده های پشتیبانی شده

Data Connect از انواع داده های اسکالر زیر پشتیبانی می کند، با انتساب به انواع PostgreSQL با استفاده از @col(dataType:) .

نوع Data Connect GraphQL توکار نوع یا
نوع سفارشی Data Connect
نوع پیش فرض PostgreSQL پشتیبانی از انواع PostgreSQL
(نام مستعار داخل پرانتز)
رشته GraphQL متن متن
بیت (n)، varbit (n)
char(n)، varchar(n)
بین المللی GraphQL بین المللی Int2 (کوچک، سریال کوچک)،
int4 (عدد صحیح، int، سریال)
شناور GraphQL شناور8 float4 (واقعی)
float8 (دقت دوگانه)
عددی (اعشاری)
بولی GraphQL بولی بولی
UUID سفارشی uuid uuid
Int64 سفارشی bigint int8 (bigint، bigserial)
عددی (اعشاری)
تاریخ سفارشی تاریخ تاریخ
مهر زمان سفارشی timestamptz

timestamptz

توجه: اطلاعات منطقه زمانی محلی ذخیره نمی شود.
PostgreSQL مُهرهای زمانی مانند UTC را تبدیل و ذخیره می کند.

بردار سفارشی بردار

بردار

به انجام جستجوی شباهت برداری با 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 درخواست جستجوی داده های مجوز بررسی می کند که فیلدهای مشخص شده در نتایج پرس و جو وجود دارد. یک عبارت Common Expression Language (CEL) برای آزمایش مقادیر فیلد استفاده می شود. راهنمای مجوز و گواهینامه را ببینید.
@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
  }
}

شامل زمینه های آرایه می شود

می توانید آزمایش کنید که یک فیلد آرایه شامل یک آیتم مشخص شده باشد.

# 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
  }
}

پرس و جوهای پیچیده

کوئری های Data Connect می توانند به داده ها بر اساس روابط بین جداول دسترسی داشته باشند. شما می توانید از روابط شی (یک به یک) یا آرایه (یک به چند) تعریف شده در طرحواره خود برای ایجاد پرس و جوهای تودرتو، یعنی واکشی داده برای یک نوع به همراه داده های یک نوع تودرتو یا مرتبط استفاده کنید.

چنین پرس و جوهایی از جادویی Data Connect _on_ و _via syntax در جستارهای ضمنی تولید شده استفاده می کنند.

شما تغییراتی در طرحواره از نسخه اولیه ما ایجاد خواهید کرد.

بسیاری به یک

بیایید نظرات را به برنامه خود اضافه کنیم، با جدول 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 ، که به شما امکان می دهد نتایج پرس و جو را از نتایج پروتکل سیمی حذف کنید.

این ویژگی ها برای جریان های مجوز مفید هستند.

طرحواره 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);

بعدش چی؟

  • بیاموزید که چگونه پرس و جوها و جهش های خود را با مجوز و گواهی ایمن کنید.
  • با نحوه فراخوانی پرسش‌ها و جهش‌های خود از یک وب SDK ، Android SDK ، iOS SDK و Flutter SDK که به‌طور خودکار ایجاد می‌شود، بیاموزید.