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

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

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

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

این راهنما با طرحی جدید برای بررسی فیلم شروع می‌شود، سپس پرسش‌ها و جهش‌های حاصل از آن طرح را پوشش می‌دهد و در نهایت فهرستی از SQL معادل طرح اصلی Data Connect ارائه می‌دهد.

طرحی برای یک برنامه بررسی فیلم

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

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

میز فیلم

طرح فیلم ها حاوی دستورالعمل های اصلی مانند:

  • @table(name) و @col(name) برای سفارشی کردن جدول SQL و نام ستون. Data Connect نام‌های snake_case را در صورت عدم مشخص کردن ایجاد می‌کند.
  • @col(dataType) برای سفارشی کردن انواع ستون SQL.
  • @default برای پیکربندی مقادیر پیش‌فرض ستون SQL در حین درج.

برای جزئیات بیشتر، اسناد مرجع برای @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
}

مقادیر سرور و اسکالرهای کلیدی

قبل از دیدن برنامه بررسی فیلم، اجازه دهید مقادیر سرور Data Connect و اسکالرهای کلیدی را معرفی کنیم.

با استفاده از مقادیر سرور ، می‌توانید به طور مؤثر به سرور اجازه دهید فیلدهای جداول شما را با استفاده از مقادیر ذخیره شده یا قابل محاسبه بر اساس عبارات سمت سرور به صورت پویا پر کند. به عنوان مثال، می‌توانید با استفاده از عبارت updatedAt: Timestamp! @default(expr: "request.time") .

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

جدول فراداده فیلم

اکنون بیایید کارگردانان فیلم را ردیابی کنیم و همچنین یک رابطه یک به یک با Movie برقرار کنیم.

فیلد مرجع را برای تعریف یک رابطه اضافه کنید.

می توانید از دستور @ref برای سفارشی کردن محدودیت کلید خارجی استفاده کنید.

  • @ref(fields) برای تعیین فیلدهای کلید خارجی.
  • @ref(references) برای تعیین فیلدهای ارجاع شده در جدول هدف. این مرجع به طور پیش فرض کلید اصلی است، اما فیلدهای با @unique نیز پشتیبانی می شوند.

برای جزئیات بیشتر، اسناد مرجع برای @ref را بررسی کنید.

# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique ensures that each Movie only has one MoiveMetadata.
  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
}

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

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

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

کاربر

در نهایت، کاربران برای برنامه شما.

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

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

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 .

# User table is keyed by Firebase Auth UID.
type User @table {
  # `@default(expr: "auth.uid")` sets it to Firebase Auth UID during insert and upsert.
  id: String! @default(expr: "auth.uid")
  username: String! @col(dataType: "varchar(50)")
  # The `user: User!` field in the Review table generates the following one-to-many query field.
  #  reviews_on_user: [Review!]!
  # The `Review` join table the following many-to-many query field.
  #  movies_via_Review: [Movie!]!
}

# Reviews is a join table tween User and Movie.
# It has a composite primary keys `userUid` and `movieId`.
# A user can leave reviews for many movies. A movie can have reviews from many users.
# User  <-> Review is a one-to-many relationship
# Movie <-> Review is a one-to-many relationship
# Movie <-> User is a many-to-many relationship
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  user: User!
  # The user field adds the following foreign key field. Feel free to uncomment and customize it.
  #  userUid: String!
  movie: Movie!
  # The movie field adds the following foreign key field. Feel free to uncomment and customize it.
  #  movieId: UUID!
  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
    }
    dislikedMovies: movies_via_Review(where: { rating: { le: 2 } }) {
      title
      genre
    }
  }
}

یک به یک

می توانید الگو را ببینید. در زیر، این طرح برای تصویر اصلاح شده است.

# 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(name) و @col(name) برای سفارشی کردن جدول SQL و نام ستون. Data Connect نام‌های snake_case را در صورت عدم مشخص کردن ایجاد می‌کند.
  • @col(dataType) برای سفارشی کردن انواع ستون SQL.
  • @default برای پیکربندی مقادیر پیش‌فرض ستون SQL در حین درج.

برای جزئیات بیشتر، اسناد مرجع برای @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
}

مقادیر سرور و اسکالرهای کلیدی

قبل از دیدن برنامه بررسی فیلم، اجازه دهید مقادیر سرور Data Connect و اسکالرهای کلیدی را معرفی کنیم.

با استفاده از مقادیر سرور ، می‌توانید به طور مؤثر به سرور اجازه دهید فیلدهای جداول شما را با استفاده از مقادیر ذخیره شده یا قابل محاسبه بر اساس عبارات سمت سرور به صورت پویا پر کند. به عنوان مثال، می‌توانید با استفاده از عبارت updatedAt: Timestamp! @default(expr: "request.time") .

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

جدول فراداده فیلم

اکنون بیایید کارگردانان فیلم را ردیابی کنیم و همچنین یک رابطه یک به یک با Movie برقرار کنیم.

فیلد مرجع را برای تعریف یک رابطه اضافه کنید.

می توانید از دستور @ref برای سفارشی کردن محدودیت کلید خارجی استفاده کنید.

  • @ref(fields) برای تعیین فیلدهای کلید خارجی.
  • @ref(references) برای تعیین فیلدهای ارجاع شده در جدول هدف. این مرجع به طور پیش فرض کلید اصلی است، اما فیلدهای با @unique نیز پشتیبانی می شوند.

برای جزئیات بیشتر، اسناد مرجع برای @ref را بررسی کنید.

# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique ensures that each Movie only has one MoiveMetadata.
  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
}

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

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

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

کاربر

در نهایت، کاربران برای برنامه شما.

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

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

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 .

# User table is keyed by Firebase Auth UID.
type User @table {
  # `@default(expr: "auth.uid")` sets it to Firebase Auth UID during insert and upsert.
  id: String! @default(expr: "auth.uid")
  username: String! @col(dataType: "varchar(50)")
  # The `user: User!` field in the Review table generates the following one-to-many query field.
  #  reviews_on_user: [Review!]!
  # The `Review` join table the following many-to-many query field.
  #  movies_via_Review: [Movie!]!
}

# Reviews is a join table tween User and Movie.
# It has a composite primary keys `userUid` and `movieId`.
# A user can leave reviews for many movies. A movie can have reviews from many users.
# User  <-> Review is a one-to-many relationship
# Movie <-> Review is a one-to-many relationship
# Movie <-> User is a many-to-many relationship
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  user: User!
  # The user field adds the following foreign key field. Feel free to uncomment and customize it.
  #  userUid: String!
  movie: Movie!
  # The movie field adds the following foreign key field. Feel free to uncomment and customize it.
  #  movieId: UUID!
  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
    }
    dislikedMovies: movies_via_Review(where: { rating: { le: 2 } }) {
      title
      genre
    }
  }
}

یک به یک

می توانید الگو را ببینید. در زیر، این طرح برای تصویر اصلاح شده است.

# 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(name) و @col(name) برای سفارشی کردن جدول SQL و نام ستون. Data Connect نام‌های snake_case را در صورت عدم مشخص کردن ایجاد می‌کند.
  • @col(dataType) برای سفارشی کردن انواع ستون SQL.
  • @default برای پیکربندی مقادیر پیش‌فرض ستون SQL در حین درج.

برای جزئیات بیشتر، اسناد مرجع برای @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
}

مقادیر سرور و اسکالرهای کلیدی

قبل از دیدن برنامه بررسی فیلم، اجازه دهید مقادیر سرور Data Connect و اسکالرهای کلیدی را معرفی کنیم.

با استفاده از مقادیر سرور ، می توانید به طور موثری به سرور به صورت پویا در جداول خود با استفاده از مقادیر ذخیره شده یا به راحتی قابل محاسبه با توجه به عبارات خاص سمت سرور جمع کنید. به عنوان مثال ، می توانید در هنگام دسترسی به قسمت با استفاده از عبارت updatedAt: Timestamp! @default(expr: "request.time") .

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

میز فوق داده فیلم

حال بیایید کارگردانان فیلم را پیگیری کنیم و همچنین رابطه یک به یک با Movie برقرار کنیم.

برای تعریف روابط ، قسمت مرجع را اضافه کنید.

می توانید از دستورالعمل @ref برای شخصی سازی محدودیت کلید خارجی استفاده کنید.

  • @ref(fields) برای مشخص کردن زمینه های کلید خارجی.
  • @ref(references) برای مشخص کردن زمینه های ذکر شده در جدول هدف. این مرجع به کلید اصلی پیش فرض می شود ، اما زمینه هایی با @unique نیز پشتیبانی می شوند.

برای اطلاعات بیشتر ، اسناد مرجع را برای @ref بررسی کنید.

# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique ensures that each Movie only has one MoiveMetadata.
  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
}

بازیگر

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

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

کاربر

در آخر ، کاربران برای برنامه شما.

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

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

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 مراجعه کنید.

  • نقشه های List GraphQL به یک آرایه یک بعدی.
    • به عنوان مثال ، نقشه های [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 ...

زبان تعریف Schema همچنین به شما امکان می دهد تا با استفاده از استدلال های دستورالعمل singular و plural به صراحت نامهایی را برای عملیات تنظیم کنید.

بخشنامه هایی برای نمایش داده ها و جهش ها

علاوه بر دستورالعمل هایی که در تعریف انواع و جداول از آنها استفاده می کنید ، Data Connect برای تقویت رفتار نمایش داده ها و جهش ها دستورالعمل های @auth ، @check ، @redact و @transaction را ارائه می دهند.

بخشنامه قابل اجرا برای توضیحات
@auth نمایش داده ها و جهش ها سیاست احراز هویت را برای پرس و جو یا جهش تعریف می کند. به راهنمای مجوز و تأیید مراجعه کنید.
@check مجوز داده های جستجوی داده ها تأیید می کند که زمینه های مشخص شده در نتایج پرس و جو وجود دارند. یک بیان زبان بیان مشترک (CEL) برای آزمایش مقادیر میدان استفاده می شود. به راهنمای مجوز و تأیید مراجعه کنید.
@redact پرس و جوها بخشی از پاسخ مشتری را رد می کند. به راهنمای مجوز و تأیید مراجعه کنید.
@transaction جهش ها اعمال می کند که یک جهش همیشه در یک معامله بانک اطلاعاتی اجرا می شود. نمونه های جهش برنامه فیلم را ببینید.

نمایش داده شد برای بانک اطلاعاتی بررسی فیلم

شما یک پرس و جو Data Connect با بیانیه عملکرد پرس و جو ، نام عملکرد ، آرگومان های صفر یا بیشتر عملیات و دستورالعمل های صفر یا بیشتر با آرگومان تعریف می کنید.

در QuickStart ، مثال Query listEmails هیچ پارامتری نگرفت. البته در بسیاری موارد ، داده های منتقل شده به زمینه های پرس و جو پویا خواهند بود. برای کار با متغیرها به عنوان یکی از مؤلفه های تعریف پرس و جو می توانید از نحو $variableName استفاده کنید.

بنابراین پرس و جو زیر:

  • تعریف نوع query
  • نام عملیات ListMoviesByGenre (پرس و جو)
  • یک آرگومان عملکرد $genre متغیر
  • یک بخشنامه واحد ، @auth .
query ListMoviesByGenre($genre: String!) @auth(level: USER)

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

بیایید به امضای نمایش داده های فزاینده پیچیده بپردازیم. شما با معرفی عبارات روابط قدرتمند و مختصر موجود در نمایش داده های ضمنی که می توانید در نمایش داده های از پیش تعریف شده خود ایجاد کنید ، پایان خواهید داد.

مقیاس های کلیدی در نمایش داده شد

اما اول ، یادداشتی در مورد مقیاس های کلیدی.

Data Connect نوع خاصی را برای مقیاس های کلیدی تعریف می کند ، که توسط _Key مشخص شده است. به عنوان مثال ، نوع یک مقیاس کلیدی برای جدول Movie ما Movie_Key است.

شما مقیاس های کلیدی را به عنوان پاسخی که توسط بیشتر جهش های ضمنی بازگردانده می شود ، بازیابی می کنید ، یا البته از پرس و جو در جایی که تمام زمینه های مورد نیاز برای ساخت کلید Scalar را بازیابی کرده اید.

نمایش داده های اتوماتیک مفرد ، مانند 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 واحد می تواند چندین فیلتر یا سایر عملیات پرس و جو را در یک درخواست کارآمد به سرور اعمال کند و به طور موثری چندین "زیرنویس" را به طور همزمان صادر کند. برای جلوگیری از برخورد نام در مجموعه داده های برگشتی ، از نام مستعار برای تمایز زیرمجموعه ها استفاده می کنید.

در اینجا یک پرس و جو وجود دارد که در آن یک عبارت از alias 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 ، بررسی ها را به برنامه خود اضافه کنیم.

# User table is keyed by Firebase Auth UID.
type User @table {
  # `@default(expr: "auth.uid")` sets it to Firebase Auth UID during insert and upsert.
  id: String! @default(expr: "auth.uid")
  username: String! @col(dataType: "varchar(50)")
  # The `user: User!` field in the Review table generates the following one-to-many query field.
  #  reviews_on_user: [Review!]!
  # The `Review` join table the following many-to-many query field.
  #  movies_via_Review: [Movie!]!
}

# Reviews is a join table tween User and Movie.
# It has a composite primary keys `userUid` and `movieId`.
# A user can leave reviews for many movies. A movie can have reviews from many users.
# User  <-> Review is a one-to-many relationship
# Movie <-> Review is a one-to-many relationship
# Movie <-> User is a many-to-many relationship
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  user: User!
  # The user field adds the following foreign key field. Feel free to uncomment and customize it.
  #  userUid: String!
  movie: Movie!
  # The movie field adds the following foreign key field. Feel free to uncomment and customize it.
  #  movieId: UUID!
  rating: Int
  reviewText: String
  reviewDate: Date! @default(expr: "request.time")
}

پرس و جو برای بسیاری به یکی

حال بیایید به یک پرس و جو بپردازیم ، با بی حس کردن ، syntax _via_ را نشان دهیم.

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

یک به یک

می توانید الگو را ببینید. در زیر ، این طرح برای تصویر اصلاح شده است.

# 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 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 مدیریت شده است ، ایجاد کنید. این اتصالات ترکیبی از یک طرحواره ، نمایش داده شد و جهش برای استفاده از داده های شما هستند.

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

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

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

طرح برای یک برنامه بررسی فیلم

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

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

میز فیلم

طرحواره برای فیلم ها شامل دستورالعمل های اصلی مانند:

  • @table(name) و @col(name) برای سفارشی کردن جدول و نام ستون SQL. Data Connect در صورت عدم مشخص شدن ، نام Snake_case را تولید می کند.
  • @col(dataType) برای سفارشی کردن انواع ستون SQL.
  • @default برای پیکربندی مقادیر پیش فرض ستون SQL در هنگام درج.

برای اطلاعات بیشتر ، اسناد مرجع را برای @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
}

مقادیر سرور و مقیاس های کلیدی

قبل از دیدن برنامه بررسی فیلم ، بیایید مقادیر سرور Data Connect و مقیاس های کلیدی را معرفی کنیم.

با استفاده از مقادیر سرور ، می توانید به طور موثری به سرور به صورت پویا در جداول خود با استفاده از مقادیر ذخیره شده یا به راحتی قابل محاسبه با توجه به عبارات خاص سمت سرور جمع کنید. به عنوان مثال ، می توانید در هنگام دسترسی به قسمت با استفاده از عبارت updatedAt: Timestamp! @default(expr: "request.time") .

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

میز فوق داده فیلم

حال بیایید کارگردانان فیلم را پیگیری کنیم و همچنین رابطه یک به یک با Movie برقرار کنیم.

برای تعریف روابط ، قسمت مرجع را اضافه کنید.

می توانید از دستورالعمل @ref برای شخصی سازی محدودیت کلید خارجی استفاده کنید.

  • @ref(fields) برای مشخص کردن زمینه های کلید خارجی.
  • @ref(references) برای مشخص کردن زمینه های ذکر شده در جدول هدف. این مرجع به کلید اصلی پیش فرض می شود ، اما زمینه هایی با @unique نیز پشتیبانی می شوند.

برای اطلاعات بیشتر ، اسناد مرجع را برای @ref بررسی کنید.

# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique ensures that each Movie only has one MoiveMetadata.
  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
}

بازیگر

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

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

کاربر

در آخر ، کاربران برای برنامه شما.

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

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

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 مراجعه کنید.

  • نقشه های List GraphQL به یک آرایه یک بعدی.
    • به عنوان مثال ، نقشه های [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 ...

زبان تعریف Schema همچنین به شما امکان می دهد تا با استفاده از استدلال های دستورالعمل singular و plural به صراحت نامهایی را برای عملیات تنظیم کنید.

بخشنامه هایی برای نمایش داده ها و جهش ها

علاوه بر دستورالعمل هایی که در تعریف انواع و جداول از آنها استفاده می کنید ، Data Connect برای تقویت رفتار نمایش داده ها و جهش ها دستورالعمل های @auth ، @check ، @redact و @transaction را ارائه می دهند.

بخشنامه قابل اجرا برای توضیحات
@auth نمایش داده ها و جهش ها سیاست احراز هویت را برای پرس و جو یا جهش تعریف می کند. به راهنمای مجوز و تأیید مراجعه کنید.
@check مجوز داده های جستجوی داده ها تأیید می کند که زمینه های مشخص شده در نتایج پرس و جو وجود دارند. یک بیان زبان بیان مشترک (CEL) برای آزمایش مقادیر میدان استفاده می شود. به راهنمای مجوز و تأیید مراجعه کنید.
@redact پرس و جوها بخشی از پاسخ مشتری را رد می کند. به راهنمای مجوز و تأیید مراجعه کنید.
@transaction جهش ها اعمال می کند که یک جهش همیشه در یک معامله بانک اطلاعاتی اجرا می شود. نمونه های جهش برنامه فیلم را ببینید.

نمایش داده شد برای بانک اطلاعاتی بررسی فیلم

شما یک پرس و جو Data Connect با بیانیه عملکرد پرس و جو ، نام عملکرد ، آرگومان های صفر یا بیشتر عملیات و دستورالعمل های صفر یا بیشتر با آرگومان تعریف می کنید.

در QuickStart ، مثال Query listEmails هیچ پارامتری نگرفت. البته در بسیاری موارد ، داده های منتقل شده به زمینه های پرس و جو پویا خواهند بود. برای کار با متغیرها به عنوان یکی از مؤلفه های تعریف پرس و جو می توانید از نحو $variableName استفاده کنید.

بنابراین پرس و جو زیر:

  • تعریف نوع query
  • نام عملیات ListMoviesByGenre (پرس و جو)
  • یک آرگومان عملکرد $genre متغیر
  • یک بخشنامه واحد ، @auth .
query ListMoviesByGenre($genre: String!) @auth(level: USER)

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

بیایید به امضای نمایش داده های فزاینده پیچیده بپردازیم. شما با معرفی عبارات روابط قدرتمند و مختصر موجود در نمایش داده های ضمنی که می توانید در نمایش داده های از پیش تعریف شده خود ایجاد کنید ، پایان خواهید داد.

مقیاس های کلیدی در نمایش داده شد

اما اول ، یادداشتی در مورد مقیاس های کلیدی.

Data Connect نوع خاصی را برای مقیاس های کلیدی تعریف می کند ، که توسط _Key مشخص شده است. به عنوان مثال ، نوع یک مقیاس کلیدی برای جدول Movie ما Movie_Key است.

شما مقیاس های کلیدی را به عنوان پاسخی که توسط بیشتر جهش های ضمنی بازگردانده می شود ، بازیابی می کنید ، یا البته از پرس و جو در جایی که تمام زمینه های مورد نیاز برای ساخت کلید Scalar را بازیابی کرده اید.

نمایش داده های اتوماتیک مفرد ، مانند 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 واحد می تواند چندین فیلتر یا سایر عملیات پرس و جو را در یک درخواست کارآمد به سرور اعمال کند و به طور موثری چندین "زیرنویس" را به طور همزمان صادر کند. برای جلوگیری از برخورد نام در مجموعه داده های برگشتی ، از نام مستعار برای تمایز زیرمجموعه ها استفاده می کنید.

در اینجا یک پرس و جو وجود دارد که در آن یک عبارت از alias 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 ، بررسی ها را به برنامه خود اضافه کنیم.

# User table is keyed by Firebase Auth UID.
type User @table {
  # `@default(expr: "auth.uid")` sets it to Firebase Auth UID during insert and upsert.
  id: String! @default(expr: "auth.uid")
  username: String! @col(dataType: "varchar(50)")
  # The `user: User!` field in the Review table generates the following one-to-many query field.
  #  reviews_on_user: [Review!]!
  # The `Review` join table the following many-to-many query field.
  #  movies_via_Review: [Movie!]!
}

# Reviews is a join table tween User and Movie.
# It has a composite primary keys `userUid` and `movieId`.
# A user can leave reviews for many movies. A movie can have reviews from many users.
# User  <-> Review is a one-to-many relationship
# Movie <-> Review is a one-to-many relationship
# Movie <-> User is a many-to-many relationship
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  user: User!
  # The user field adds the following foreign key field. Feel free to uncomment and customize it.
  #  userUid: String!
  movie: Movie!
  # The movie field adds the following foreign key field. Feel free to uncomment and customize it.
  #  movieId: UUID!
  rating: Int
  reviewText: String
  reviewDate: Date! @default(expr: "request.time")
}

پرس و جو برای بسیاری به یکی

حال بیایید به یک پرس و جو بپردازیم ، با بی حس کردن ، syntax _via_ را نشان دهیم.

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

یک به یک

می توانید الگو را ببینید. در زیر ، این طرح برای تصویر اصلاح شده است.

# 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 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 به صورت خودکار فراخوانی کنید.