Firebase Data Connect به شما امکان می دهد برای نمونه های PostgreSQL خود که با Google Cloud SQL مدیریت می شوند، رابط ایجاد کنید. این رابطها ترکیبی از طرحواره، پرسشها و جهشها برای استفاده از دادههای شما هستند.
راهنمای شروع یک طرح برنامه بررسی فیلم را برای PostgreSQL معرفی کرد و این راهنما نگاهی عمیق تر به نحوه طراحی طرحواره های Data Connect برای PostgreSQL دارد.
این راهنما پرس و جوها و جهش های Data Connect را با نمونه های طرحواره جفت می کند. چرا پرس و جوها (و جهش ها ) را در راهنمای طرحواره های Data Connect مورد بحث قرار می دهیم؟ مانند سایر پلتفرمهای مبتنی بر GraphQL، Firebase Data Connect یک پلتفرم توسعه اولین پرس و جو است، بنابراین بهعنوان یک توسعهدهنده، در مدلسازی دادههای خود به دادههایی فکر میکنید که مشتریانتان به آن نیاز دارند، که تا حد زیادی بر طرح دادهای که برای خود ایجاد میکنید، تأثیر میگذارد. پروژه
این راهنما با طرحی جدید برای بررسی فیلم شروع میشود، سپس پرسشها و جهشهای حاصل از آن طرح را پوشش میدهد و در نهایت فهرستی از SQL معادل طرح اصلی Data Connect ارائه میدهد.
طرحی برای یک برنامه بررسی فیلم
تصور کنید می خواهید سرویسی بسازید که به کاربران اجازه می دهد نظرات فیلم ها را ارسال و مشاهده کنند.
برای چنین اپلیکیشنی به یک طرح اولیه نیاز دارید. بعداً این طرح را برای ایجاد پرس و جوهای رابطه ای پیچیده گسترش خواهید داد.
میز فیلم
طرح فیلم ها حاوی دستورالعمل های اصلی مانند:
-
@table
، که به ما امکان می دهد نام عملیات را با استفاده از آرگومان هایsingular
وplural
تنظیم کنیم -
@col
برای تنظیم صریح نام ستون ها -
@default
برای اجازه دادن به تنظیمات پیش فرض.
# Movies
type Movie
@table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
title: String!
releaseYear: Int @col(name: "release_year")
genre: String
rating: Int @col(name: "rating")
description: String @col(name: "description")
}
مقادیر سرور و اسکالرهای کلیدی
قبل از دیدن برنامه بررسی فیلم، اجازه دهید مقادیر سرور Data Connect و اسکالرهای کلیدی را معرفی کنیم.
با استفاده از مقادیر سرور ، میتوانید به طور مؤثر به سرور اجازه دهید فیلدهای جداول شما را با استفاده از مقادیر ذخیره شده یا قابل محاسبه بر اساس عبارات سمت سرور به صورت پویا پر کند. به عنوان مثال، میتوانید با استفاده از عبارت updatedAt: Timestamp! @default(expr: "request.time")
.
اسکالرهای کلیدی شناسه های شی مختصر هستند که Data Connect به طور خودکار از فیلدهای کلیدی در طرحواره های شما جمع آوری می کند. اسکالرهای کلیدی در مورد کارایی هستند و به شما امکان می دهند در یک تماس اطلاعاتی درباره هویت و ساختار داده های خود پیدا کنید. آنها به ویژه زمانی مفید هستند که می خواهید اقدامات متوالی را روی رکوردهای جدید انجام دهید و به یک شناسه منحصر به فرد برای ارسال به عملیات آینده نیاز دارید، و همچنین زمانی که می خواهید به کلیدهای رابطه ای برای انجام عملیات پیچیده تر اضافی دسترسی داشته باشید.
جدول فراداده فیلم
اکنون بیایید کارگردانان فیلم را ردیابی کنیم و همچنین یک رابطه یک به یک با Movie
برقرار کنیم.
دستور @ref
را برای تعریف روابط اضافه کنید.
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
@table(
name: "MovieMetadata"
) {
# @ref creates a field in the current table (MovieMetadata) that holds the
# primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID <- this is created by the above @ref
director: String @col(name: "director")
}
بازیگر و بازیگر سینما
در مرحله بعد، شما می خواهید بازیگران در فیلم های شما بازی کنند، و از آنجایی که بین فیلم ها و بازیگران رابطه چند به چند دارید، یک جدول پیوستن ایجاد کنید.
# Actors
# Suppose an actor can participate in multiple movies and movies can have multiple actors
# Movie - Actors (or vice versa) is a many to many relationship
type Actor @table(name: "Actors", singular: "actor", plural: "actors") {
id: UUID! @col(name: "actor_id") @default(expr: "uuidV4()")
name: String! @col(name: "name", dataType: "varchar(30)")
}
# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary key(s) of this table
# In this case, the keys are [movieId, actorId], the generated fields of the reference types [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
# @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID! <- this is created by the above @ref, see: implicit.gql
actor: Actor! @ref
# actorId: UUID! <- this is created by the above @ref, see: implicit.gql
role: String! @col(name: "role") # "main" or "supporting"
# optional other fields
}
کاربر
در نهایت، کاربران برای برنامه شما.
# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship, movie:reviews is a one to many relationship, movie:user is a many to many relationship
type User
@table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
auth: String @col(name: "user_auth") @default(expr: "auth.uid")
username: String! @col(name: "username", dataType: "varchar(30)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
انواع داده های پشتیبانی شده
Data Connect از انواع داده های اسکالر زیر پشتیبانی می کند، با انتساب به انواع PostgreSQL با استفاده از @col(dataType:)
.
نوع Data Connect | GraphQL توکار نوع یا نوع سفارشی Data Connect | نوع پیش فرض PostgreSQL | پشتیبانی از انواع PostgreSQL (نام مستعار داخل پرانتز) |
---|---|---|---|
رشته | GraphQL | متن | متن بیت (n)، varbit (n) char(n)، varchar(n) |
بین المللی | GraphQL | بین المللی | Int2 (کوچک، سریال کوچک)، int4 (عدد صحیح، int، سریال) |
شناور | GraphQL | شناور8 | float4 (واقعی) float8 (دقت دوگانه) عددی (اعشاری) |
بولی | GraphQL | بولی | بولی |
UUID | سفارشی | uuid | uuid |
Int64 | سفارشی | bigint | int8 (bigint، bigserial) عددی (اعشاری) |
تاریخ | سفارشی | تاریخ | تاریخ |
مهر زمان | سفارشی | timestamptz | timestamptz توجه: اطلاعات منطقه زمانی محلی ذخیره نمی شود. |
بردار | سفارشی | بردار | بردار به انجام جستجوی شباهت برداری با Vertex AI مراجعه کنید. |
- GraphQL
List
به یک آرایه یک بعدی نگاشت می شود.- برای مثال،
[Int]
بهint5[]
,[Any]
بهjsonb[]
نقشه میدهد. - Data Connect از آرایه های تو در تو پشتیبانی نمی کند.
- برای مثال،
کوئری ها و جهش های ضمنی و از پیش تعریف شده
جستارها و جهش های Data Connect شما مجموعه ای از پرس و جوهای ضمنی و جهش های ضمنی ایجاد شده توسط Data Connect را بر اساس انواع و روابط نوع در طرح شما گسترش می دهند. هر زمان که شما طرحواره خود را ویرایش می کنید، پرس و جوها و جهش های ضمنی توسط ابزارهای محلی ایجاد می شوند.
در فرآیند توسعه خود، پرس و جوهای از پیش تعریف شده و جهش های از پیش تعریف شده را بر اساس این عملیات ضمنی پیاده سازی خواهید کرد.
پرس و جو ضمنی و نامگذاری جهش
Data Connect نام های مناسب را برای پرس و جوها و جهش های ضمنی از اعلان های نوع طرحواره شما استنتاج می کند. به عنوان مثال، با کار با یک منبع PostgreSQL، اگر جدولی به نام Movie
تعریف کنید، سرور به صورت ضمنی تولید می کند:
- پرسوجوها برای جدولهای تکی با نامهای دوستانه
movie
(مفرد، برای بازیابی نتایج منفرد با عبور ارگهایی مانندeq
) وmovies
(جمع، برای بازیابی فهرستهای نتایج، ارگهایی مانندgt
و عملیاتی مانندorderby
) استفاده میکنند. Data Connect همچنین پرس و جوهایی را برای عملیات های چند جدولی و رابطه ای با نام های صریح مانندactors_on_movies
یاactors_via_actormovie
ایجاد می کند. - جهش هایی با نام
movie_insert
,movie_upsert
...
زبان تعریف طرحواره همچنین به شما این امکان را می دهد که با استفاده از آرگومان های دستوری singular
و plural
، نام عملیات را به صراحت تنظیم کنید.
دستورالعمل برای پرس و جو و جهش
علاوه بر دستورالعملهایی که در تعریف انواع و جداول استفاده میکنید، Data Connect دستورات @auth
، @check
، @redact
و @transaction
را برای تقویت رفتار کوئریها و جهشها ارائه میکند.
بخشنامه | قابل اجرا برای | توضیحات |
---|---|---|
@auth | پرس و جو و جهش | خط مشی احراز هویت را برای یک پرس و جو یا جهش تعریف می کند. راهنمای مجوز و گواهینامه را ببینید. |
@check | درخواست جستجوی داده های مجوز | بررسی می کند که فیلدهای مشخص شده در نتایج پرس و جو وجود دارد. یک عبارت Common Expression Language (CEL) برای آزمایش مقادیر فیلد استفاده می شود. راهنمای مجوز و گواهینامه را ببینید. |
@redact | پرس و جوها | بخشی از پاسخ مشتری را ویرایش می کند. راهنمای مجوز و گواهینامه را ببینید. |
@transaction | جهش ها | الزام می کند که یک جهش همیشه در یک تراکنش پایگاه داده اجرا شود. نمونه های جهش برنامه فیلم را ببینید. |
پرس و جو برای پایگاه داده نقد و بررسی فیلم
شما یک کوئری Data Connect را با اعلان نوع عملیات پرس و جو، نام عملیات، آرگومان های عملیات صفر یا بیشتر، و صفر یا بیشتر دستورالعمل با آرگومان ها تعریف می کنید.
در شروع سریع، پرس و جوی مثال listEmails
هیچ پارامتری نداشت. البته در بسیاری از موارد داده های ارسال شده به فیلدهای پرس و جو پویا خواهند بود. میتوانید از نحو $variableName
برای کار با متغیرها بهعنوان یکی از اجزای تعریف پرسوجو استفاده کنید.
بنابراین پرس و جو زیر دارد:
- تعریف نوع
query
- نام عملیات
ListMoviesByGenre
(پرس و جو). - یک آرگومان عملیات
$genre
متغییر - یک دستورالعمل واحد،
@auth
.
query ListMoviesByGenre($genre: String!) @auth(level: USER)
هر آرگومان پرس و جو نیاز به یک اعلان نوع، یک نوع داخلی مانند String
، یا یک نوع سفارشی، طرحواره تعریف شده مانند Movie
دارد.
بیایید به امضای پرس و جوهای پیچیده تر نگاه کنیم. شما با معرفی عبارات ارتباطی قدرتمند و مختصر موجود در پرسوجوهای ضمنی که میتوانید در پرسوجوهای از پیش تعریفشده خود بر روی آنها بسازید، به پایان میرسید.
اسکالرهای کلیدی در پرس و جوها
اما ابتدا یک نکته در مورد اسکالرهای کلیدی.
Data Connect نوع خاصی را برای اسکالرهای کلیدی تعریف می کند که با _Key
مشخص می شود. به عنوان مثال، نوع اسکالر کلید برای جدول Movie
ما Movie_Key
است.
شما اسکالرهای کلیدی را به عنوان پاسخی که توسط اکثر جهشهای ضمنی برگردانده میشود، یا البته از کوئریهایی که تمام فیلدهای مورد نیاز برای ساختن کلید اسکالر را بازیابی کردهاید، بازیابی میکنید.
پرسوجوهای خودکار منفرد، مانند movie
در مثال در حال اجرا، از یک آرگومان کلیدی پشتیبانی میکنند که یک اسکالر کلیدی را میپذیرد.
شما ممکن است یک اسکالر کلیدی را به صورت تحت اللفظی پاس کنید. اما، می توانید متغیرهایی را برای ارسال اسکالرهای کلیدی به عنوان ورودی تعریف کنید.
query GetMovie($myKey: Movie_Key!) {
movie(key: $myKey) { title }
}
اینها را می توان در درخواست JSON مانند این (یا سایر قالب های سریال سازی) ارائه کرد:
{
# …
"variables": {
"myKey": {"foo": "some-string-value", "bar": 42}
}
}
به لطف تجزیه اسکالر سفارشی، یک Movie_Key
نیز می تواند با استفاده از نحو شی که ممکن است حاوی متغیرهایی باشد ساخته شود. این بیشتر زمانی مفید است که بخواهید به دلایلی اجزای جداگانه را به متغیرهای مختلف تقسیم کنید.
نام مستعار در پرس و جوها
Data Connect از نام مستعار GraphQL در کوئری ها پشتیبانی می کند. با نام مستعار، نام داده هایی را که در نتایج یک پرس و جو برگردانده می شوند، تغییر می دهید. یک کوئری Data Connect می تواند چندین فیلتر یا عملیات پرس و جوی دیگر را در یک درخواست کارآمد به سرور اعمال کند و به طور موثر چندین «پرس و جوی فرعی» را همزمان صادر کند. برای جلوگیری از تصادم نام در مجموعه داده های برگشتی، از نام مستعار برای تشخیص پرس و جوهای فرعی استفاده می کنید.
در اینجا یک جستجو وجود دارد که در آن یک عبارت از نام مستعار mostPopular
استفاده می کند.
query ReviewTopPopularity($genre: String) {
mostPopular: review(first: {
where: {genre: {eq: $genre}},
orderBy: {popularity: DESC}
}) { … }
}
پرس و جوهای ساده با فیلتر
پرس و جوهای Data Connect به تمام فیلترهای رایج SQL و عملیات سفارش نگاشت می شوند.
عملگرهای where
و orderBy
(پرسشهای مفرد، جمع)
تمام ردیف های منطبق از جدول (و پیوندهای تودرتو) را برمی گرداند. اگر هیچ رکوردی با فیلتر مطابقت نداشته باشد، آرایه خالی را برمیگرداند.
query MovieByTopRating($genre: String) {
mostPopular: movies(
where: { genre: { eq: $genre } }, orderBy: { rating: DESC }
) {
# graphql: list the fields from the results to return
id
title
genre
description
}
}
query MoviesByReleaseYear($min: Int, $max: Int) {
movies(where: {releaseYear: {le: $max, ge: $min}}, orderBy: [{releaseYear: ASC}]) { … }
}
عملگرهای limit
و offset
(پرس و جوهای مفرد، جمع)
می توانید صفحه بندی را روی نتایج انجام دهید. این آرگومانها پذیرفته میشوند اما به نتایج بازگردانده نمیشوند.
query MoviesTop10 {
movies(orderBy: [{ rating: DESC }], limit: 10) {
# graphql: list the fields from the results to return
title
}
}
شامل زمینه های آرایه می شود
می توانید آزمایش کنید که یک فیلد آرایه شامل یک آیتم مشخص شده باشد.
# Filter using arrays and embedded fields.
query ListMoviesByTag($tag: String!) {
movies(where: { tags: { includes: $tag }}) {
# graphql: list the fields from the results to return
id
title
}
}
عملیات رشته و عبارات منظم
جستارهای شما می توانند از عملیات جستجو و مقایسه رشته ای معمولی از جمله عبارات منظم استفاده کنند. توجه داشته باشید برای کارایی شما چندین عملیات را در اینجا دسته بندی می کنید و آنها را با نام مستعار رفع می کنید.
query MoviesTitleSearch($prefix: String, $suffix: String, $contained: String, $regex: String) {
prefixed: movies(where: {title: {startsWith: $prefix}}) {...}
suffixed: movies(where: {title: {endsWith: $suffix}}) {...}
contained: movies(where: {title: {contains: $contained}}) {...}
matchRegex: movies(where: {title: {pattern: {regex: $regex}}}) {...}
}
or
و and
برای فیلترهای ترکیبی
or
و and
برای منطق پیچیده تر استفاده کنید.
query ListMoviesByGenreAndGenre($minRating: Int!, $genre: String) {
movies(
where: { _or: [{ rating: { ge: $minRating } }, { genre: { eq: $genre } }] }
) {
# graphql: list the fields from the results to return
title
}
}
پرس و جوهای پیچیده
کوئری های Data Connect می توانند به داده ها بر اساس روابط بین جداول دسترسی داشته باشند. شما می توانید از روابط شی (یک به یک) یا آرایه (یک به چند) تعریف شده در طرحواره خود برای ایجاد پرس و جوهای تودرتو، یعنی واکشی داده برای یک نوع به همراه داده های یک نوع تودرتو یا مرتبط استفاده کنید.
چنین پرس و جوهایی از جادویی Data Connect _on_
و _via
syntax در جستارهای ضمنی تولید شده استفاده می کنند.
شما تغییراتی در طرحواره از نسخه اولیه ما ایجاد خواهید کرد.
بسیاری به یک
بیایید نظرات را به برنامه خود اضافه کنیم، با جدول Review
و تغییراتی در User
.
# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship,
# movie:reviews is a one to many relationship,
# movie:user is a many to many relationship
type User
@table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
auth: String @col(name: "user_auth") @default(expr: "auth.uid")
username: String! @col(name: "username", dataType: "varchar(30)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
# Reviews
type Review @table(name: "Reviews", key: ["movie", "user"]) {
id: UUID! @col(name: "review_id") @default(expr: "uuidV4()")
user: User! @ref
movie: Movie! @ref
rating: Int
reviewText: String
reviewDate: Date! @default(expr: "request.time")
}
پرس و جو برای خیلی به یک
حالا بیایید به یک پرس و جو نگاه کنیم، با نام مستعار، برای نشان دادن نحو _via_
.
query UserMoviePreferences($username: String!) @auth(level: USER) {
users(where: { username: { eq: $username } }) {
likedMovies: movies_via_review(where: { rating: { ge: 4 } }) {
title
genre
description
}
dislikedMovies: movies_via_review(where: { rating: { le: 2 } }) {
title
genre
description
}
}
}
یک به یک
می توانید الگو را ببینید. در زیر، این طرح برای تصویر اصلاح شده است.
# Movies
type Movie
@table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
title: String!
releaseYear: Int @col(name: "release_year")
genre: String
rating: Int @col(name: "rating")
description: String @col(name: "description")
tags: [String] @col(name: "tags")
}
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
@table(
name: "MovieMetadata"
) {
# @ref creates a field in the current table (MovieMetadata) that holds the primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID <- this is created by the above @ref
director: String @col(name: "director")
}
extend type MovieMetadata {
movieId: UUID! # matches primary key of referenced type
...
}
extend type Movie {
movieMetadata: MovieMetadata # can only be non-nullable on ref side
# conflict-free name, always generated
movieMetadatas_on_movie: MovieMetadata
}
یک به یک پرس و جو کنید
می توانید با استفاده از نحو _on_
پرس و جو کنید.
# One to one
query GetMovieMetadata($id: UUID!) @auth(level: PUBLIC) {
movie(id: $id) {
movieMetadatas_on_movie {
director
}
}
}
خیلی به خیلی ها
فیلم ها به بازیگر نیاز دارند و بازیگران به فیلم. آنها روابط بسیار زیادی دارند که می توانید با جدول پیوستن MovieActors
مدل کنید.
# MovieActors Join Table Definition
type MovieActors @table(
key: ["movie", "actor"] # join key triggers many-to-many generation
) {
movie: Movie!
actor: Actor!
}
# generated extensions for the MovieActors join table
extend type MovieActors {
movieId: UUID!
actorId: UUID!
}
# Extensions for Actor and Movie to handle many-to-many relationships
extend type Movie {
movieActors: [MovieActors!]! # standard many-to-one relation to join table
actors: [Actor!]! # many-to-many via join table
movieActors_on_actor: [MovieActors!]!
# since MovieActors joins distinct types, type name alone is sufficiently precise
actors_via_MovieActors: [Actor!]!
}
extend type Actor {
movieActors: [MovieActors!]! # standard many-to-one relation to join table
movies: [Movie!]! # many-to-many via join table
movieActors_on_movie: [MovieActors!]!
movies_via_MovieActors: [Movie!]!
}
پرس و جو برای بسیاری از بسیاری
بیایید به یک پرس و جو با نام مستعار نگاه کنیم تا نحو _via_
را نشان دهیم.
query GetMovieCast($movieId: UUID!, $actorId: UUID!) @auth(level: PUBLIC) {
movie(id: $movieId) {
mainActors: actors_via_MovieActor(where: { role: { eq: "main" } }) {
name
}
supportingActors: actors_via_MovieActor(
where: { role: { eq: "supporting" } }
) {
name
}
}
actor(id: $actorId) {
mainRoles: movies_via_MovieActor(where: { role: { eq: "main" } }) {
title
}
supportingRoles: movies_via_MovieActor(
where: { role: { eq: "supporting" } }
) {
title
}
}
}
جهش برای پایگاه داده نقد فیلم
همانطور که گفته شد، زمانی که جدولی را در طرحواره خود تعریف می کنید، Data Connect جهش های ضمنی اساسی را برای هر جدول ایجاد می کند.
type Movie @table { ... }
extend type Mutation {
# Insert a row into the movie table.
movie_insert(...): Movie_Key!
# Upsert a row into movie."
movie_upsert(...): Movie_Key!
# Update a row in Movie. Returns null if a row with the specified id/key does not exist
movie_update(...): Movie_Key
# Update rows based on a filter in Movie.
movie_updateMany(...): Int!
# Delete a single row in Movie. Returns null if a row with the specified id/key does not exist
movie_delete(...): Movie_Key
# Delete rows based on a filter in Movie.
movie_deleteMany(...): Int!
}
با استفاده از این موارد، می توانید موارد پیچیده هسته ای CRUD را پیاده سازی کنید. پنج بار سریع بگو!
دستورالعمل @transaction
این دستورالعمل الزام می کند که یک جهش همیشه در یک تراکنش پایگاه داده اجرا شود.
جهش با @transaction
تضمین شده است که یا به طور کامل موفق شود یا به طور کامل شکست بخورد. اگر هر یک از فیلدهای داخل تراکنش از کار بیفتد، کل تراکنش برگردانده می شود. از نقطه نظر مشتری، هر شکست به گونه ای رفتار می کند که گویی کل درخواست با یک خطای درخواست شکست خورده است و اجرا آغاز نشده است.
جهش های بدون @transaction
هر فیلد ریشه را یکی پس از دیگری به ترتیب اجرا می کنند. هر گونه خطا را به عنوان خطای میدانی جزئی نشان می دهد، اما تاثیرات اجرای بعدی را نه.
ایجاد کنید
بیایید کارهای اساسی انجام دهیم.
# Create a movie based on user input
mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
movie_insert(data: {
title: $title
releaseYear: $releaseYear
genre: $genre
rating: $rating
})
}
# Create a movie with default values
mutation CreateMovie2 {
movie_insert(data: {
title: "Sherlock Holmes"
releaseYear: 2009
genre: "Mystery"
rating: 5
})
}
یا یک تاپیک
# Movie upsert using combination of variables and literals
mutation UpsertMovie($title: String!) {
movie_upsert(data: {
title: $title
releaseYear: 2009
genre: "Mystery"
rating: 5
genre: "Mystery/Thriller"
})
}
به روز رسانی را انجام دهید
در اینجا به روز رسانی است. تهیهکنندگان و کارگردانان مطمئناً امیدوارند که این رتبهبندیهای متوسط رو به رشد باشد.
mutation UpdateMovie(
$id: UUID!,
$genre: String!,
$rating: Int!,
$description: String!
) {
movie_update(id: $id, data: {
genre: $genre
rating: $rating
description: $description
})
}
# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $ratingIncrement: Int!) {
movie_updateMany(
where: { genre: { eq: $genre } },
update: { rating: { inc: $ratingIncrement } }
)
}
حذف ها را انجام دهید
البته می توانید داده های فیلم را حذف کنید. محافظان فیلم مطمئناً مایلند که فیلمهای فیزیکی تا زمانی که ممکن است نگهداری شوند.
# Delete by key
mutation DeleteMovie($id: UUID!) {
movie_delete(id: $id)
}
در اینجا می توانید از _deleteMany
استفاده کنید.
# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
movie_deleteMany(where: { rating: { le: $minRating } })
}
جهش را روی روابط بنویسید
نحوه استفاده از جهش _upsert
ضمنی را در یک رابطه مشاهده کنید.
# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
movieMetadata_upsert(
data: { movie: { id: $movieId }, director: $director }
)
}
درخواست جستجوی داده های مجوز
جهش های Data Connect را می توان با پرس و جو در پایگاه داده و تأیید نتایج پرس و جو با عبارات CEL مجاز کرد. این زمانی مفید است که در حال نوشتن روی یک جدول هستید و باید محتویات یک ردیف را در جدول دیگری بررسی کنید.
این ویژگی پشتیبانی می کند:
- دستورالعمل
@check
، که به شما امکان میدهد محتویات فیلدها را ارزیابی کنید و بر اساس نتایج چنین ارزیابی:- ایجاد، به روز رسانی و حذف های تعریف شده توسط جهش را ادامه دهید
- از مقادیری که توسط پرس و جو به مشتریان بازگردانده می شود برای اجرای منطق متفاوت در مشتریان خود استفاده کنید
- دستورالعمل
@redact
، که به شما امکان می دهد نتایج پرس و جو را از نتایج پروتکل سیمی حذف کنید.
این ویژگی ها برای جریان های مجوز مفید هستند.
طرحواره SQL معادل
-- Movies Table
CREATE TABLE Movies (
movie_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
title VARCHAR(255) NOT NULL,
release_year INT,
genre VARCHAR(30),
rating INT,
description TEXT,
tags TEXT[]
);
-- Movie Metadata Table
CREATE TABLE MovieMetadata (
movie_id UUID REFERENCES Movies(movie_id) UNIQUE,
director VARCHAR(255) NOT NULL,
PRIMARY KEY (movie_id)
);
-- Actors Table
CREATE TABLE Actors (
actor_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(30) NOT NULL
);
-- MovieActor Join Table for Many-to-Many Relationship
CREATE TABLE MovieActor (
movie_id UUID REFERENCES Movies(movie_id),
actor_id UUID REFERENCES Actors(actor_id),
role VARCHAR(50) NOT NULL, # "main" or "supporting"
PRIMARY KEY (movie_id, actor_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id),
FOREIGN KEY (actor_id) REFERENCES Actors(actor_id)
);
-- Users Table
CREATE TABLE Users (
user_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_auth VARCHAR(255) NOT NULL
username VARCHAR(30) NOT NULL
);
-- Reviews Table
CREATE TABLE Reviews (
review_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES Users(user_id),
movie_id UUID REFERENCES Movies(movie_id),
rating INT,
review_text TEXT,
review_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (movie_id, user_id)
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
-- Self Join Example for Movie Sequel Relationship
ALTER TABLE Movies
ADD COLUMN sequel_to UUID REFERENCES Movies(movie_id);
بعدش چی؟
- بیاموزید که چگونه پرس و جوها و جهش های خود را با مجوز و گواهی ایمن کنید.
- با نحوه فراخوانی پرسشها و جهشهای خود از یک وب SDK ، Android SDK ، iOS SDK و Flutter SDK که بهطور خودکار ایجاد میشود، بیاموزید.
Firebase Data Connect به شما امکان می دهد برای نمونه های PostgreSQL خود که با Google Cloud SQL مدیریت می شوند، رابط ایجاد کنید. این رابطها ترکیبی از طرحواره، پرسشها و جهشها برای استفاده از دادههای شما هستند.
راهنمای شروع یک طرح برنامه بررسی فیلم را برای PostgreSQL معرفی کرد و این راهنما نگاهی عمیق تر به نحوه طراحی طرحواره های Data Connect برای PostgreSQL دارد.
این راهنما پرس و جوها و جهش های Data Connect را با نمونه های طرحواره جفت می کند. چرا پرس و جوها (و جهش ها ) را در راهنمای طرحواره های Data Connect مورد بحث قرار می دهیم؟ مانند سایر پلتفرمهای مبتنی بر GraphQL، Firebase Data Connect یک پلتفرم توسعه اولین پرس و جو است، بنابراین بهعنوان یک توسعهدهنده، در مدلسازی دادههای خود به دادههایی فکر میکنید که مشتریانتان به آن نیاز دارند، که تا حد زیادی بر طرح دادهای که برای خود ایجاد میکنید، تأثیر میگذارد. پروژه
این راهنما با طرحی جدید برای بررسی فیلم شروع میشود، سپس پرسشها و جهشهای حاصل از آن طرح را پوشش میدهد و در نهایت فهرستی از SQL معادل طرح اصلی Data Connect ارائه میدهد.
طرحی برای یک برنامه بررسی فیلم
تصور کنید می خواهید سرویسی بسازید که به کاربران اجازه می دهد نظرات فیلم ها را ارسال و مشاهده کنند.
برای چنین اپلیکیشنی به یک طرح اولیه نیاز دارید. بعداً این طرح را برای ایجاد پرس و جوهای رابطه ای پیچیده گسترش خواهید داد.
میز فیلم
طرح فیلم ها حاوی دستورالعمل های اصلی مانند:
-
@table
، که به ما امکان می دهد نام عملیات را با استفاده از آرگومان هایsingular
وplural
تنظیم کنیم -
@col
برای تنظیم صریح نام ستون ها -
@default
برای اجازه دادن به تنظیمات پیش فرض.
# Movies
type Movie
@table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
title: String!
releaseYear: Int @col(name: "release_year")
genre: String
rating: Int @col(name: "rating")
description: String @col(name: "description")
}
مقادیر سرور و اسکالرهای کلیدی
قبل از دیدن برنامه بررسی فیلم، اجازه دهید مقادیر سرور Data Connect و اسکالرهای کلیدی را معرفی کنیم.
با استفاده از مقادیر سرور ، میتوانید به طور مؤثر به سرور اجازه دهید فیلدهای جداول شما را با استفاده از مقادیر ذخیره شده یا قابل محاسبه بر اساس عبارات سمت سرور به صورت پویا پر کند. به عنوان مثال، میتوانید با استفاده از عبارت updatedAt: Timestamp! @default(expr: "request.time")
.
اسکالرهای کلیدی شناسه های شی مختصر هستند که Data Connect به طور خودکار از فیلدهای کلیدی در طرحواره های شما جمع آوری می کند. اسکالرهای کلیدی در مورد کارایی هستند و به شما امکان می دهند در یک تماس اطلاعاتی درباره هویت و ساختار داده های خود پیدا کنید. آنها به ویژه زمانی مفید هستند که می خواهید اقدامات متوالی را روی رکوردهای جدید انجام دهید و به یک شناسه منحصر به فرد برای ارسال به عملیات آینده نیاز دارید، و همچنین زمانی که می خواهید به کلیدهای رابطه ای برای انجام عملیات پیچیده تر اضافی دسترسی داشته باشید.
جدول فراداده فیلم
اکنون بیایید کارگردانان فیلم را ردیابی کنیم و همچنین یک رابطه یک به یک با Movie
برقرار کنیم.
دستور @ref
را برای تعریف روابط اضافه کنید.
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
@table(
name: "MovieMetadata"
) {
# @ref creates a field in the current table (MovieMetadata) that holds the
# primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID <- this is created by the above @ref
director: String @col(name: "director")
}
بازیگر و بازیگر سینما
در مرحله بعد، شما می خواهید بازیگران در فیلم های شما بازی کنند، و از آنجایی که بین فیلم ها و بازیگران رابطه چند به چند دارید، یک جدول پیوستن ایجاد کنید.
# Actors
# Suppose an actor can participate in multiple movies and movies can have multiple actors
# Movie - Actors (or vice versa) is a many to many relationship
type Actor @table(name: "Actors", singular: "actor", plural: "actors") {
id: UUID! @col(name: "actor_id") @default(expr: "uuidV4()")
name: String! @col(name: "name", dataType: "varchar(30)")
}
# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary key(s) of this table
# In this case, the keys are [movieId, actorId], the generated fields of the reference types [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
# @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID! <- this is created by the above @ref, see: implicit.gql
actor: Actor! @ref
# actorId: UUID! <- this is created by the above @ref, see: implicit.gql
role: String! @col(name: "role") # "main" or "supporting"
# optional other fields
}
کاربر
در نهایت، کاربران برای برنامه شما.
# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship, movie:reviews is a one to many relationship, movie:user is a many to many relationship
type User
@table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
auth: String @col(name: "user_auth") @default(expr: "auth.uid")
username: String! @col(name: "username", dataType: "varchar(30)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
انواع داده های پشتیبانی شده
Data Connect از انواع داده های اسکالر زیر پشتیبانی می کند، با انتساب به انواع PostgreSQL با استفاده از @col(dataType:)
.
نوع Data Connect | GraphQL توکار نوع یا نوع سفارشی Data Connect | نوع پیش فرض PostgreSQL | پشتیبانی از انواع PostgreSQL (نام مستعار داخل پرانتز) |
---|---|---|---|
رشته | GraphQL | متن | متن بیت (n)، varbit (n) char(n)، varchar(n) |
بین المللی | GraphQL | بین المللی | Int2 (کوچک، سریال کوچک)، int4 (عدد صحیح، int، سریال) |
شناور | GraphQL | شناور8 | float4 (واقعی) float8 (دقت دوگانه) عددی (اعشاری) |
بولی | GraphQL | بولی | بولی |
UUID | سفارشی | uuid | uuid |
Int64 | سفارشی | bigint | int8 (bigint، bigserial) عددی (اعشاری) |
تاریخ | سفارشی | تاریخ | تاریخ |
مهر زمان | سفارشی | timestamptz | timestamptz توجه: اطلاعات منطقه زمانی محلی ذخیره نمی شود. |
بردار | سفارشی | بردار | بردار به انجام جستجوی شباهت برداری با Vertex AI مراجعه کنید. |
- GraphQL
List
به یک آرایه یک بعدی نگاشت می شود.- برای مثال،
[Int]
بهint5[]
,[Any]
بهjsonb[]
نقشه میدهد. - Data Connect از آرایه های تو در تو پشتیبانی نمی کند.
- برای مثال،
کوئری ها و جهش های ضمنی و از پیش تعریف شده
جستارها و جهش های Data Connect شما مجموعه ای از پرس و جوهای ضمنی و جهش های ضمنی ایجاد شده توسط Data Connect را بر اساس انواع و روابط نوع در طرح شما گسترش می دهند. هر زمان که شما طرحواره خود را ویرایش می کنید، پرس و جوها و جهش های ضمنی توسط ابزارهای محلی ایجاد می شوند.
در فرآیند توسعه خود، پرس و جوهای از پیش تعریف شده و جهش های از پیش تعریف شده را بر اساس این عملیات ضمنی پیاده سازی خواهید کرد.
پرس و جو ضمنی و نامگذاری جهش
Data Connect نام های مناسب را برای پرس و جوها و جهش های ضمنی از اعلان های نوع طرحواره شما استنتاج می کند. به عنوان مثال، با کار با یک منبع PostgreSQL، اگر جدولی به نام Movie
تعریف کنید، سرور به صورت ضمنی تولید می کند:
- پرسوجوها برای جدولهای تکی با نامهای دوستانه
movie
(مفرد، برای بازیابی نتایج منفرد با عبور ارگهایی مانندeq
) وmovies
(جمع، برای بازیابی فهرستهای نتایج، ارگهایی مانندgt
و عملیاتی مانندorderby
) استفاده میکنند. Data Connect همچنین پرس و جوهایی را برای عملیات های چند جدولی و رابطه ای با نام های صریح مانندactors_on_movies
یاactors_via_actormovie
ایجاد می کند. - جهش هایی با نام
movie_insert
,movie_upsert
...
زبان تعریف طرحواره همچنین به شما این امکان را می دهد که با استفاده از آرگومان های دستوری singular
و plural
، نام عملیات را به صراحت تنظیم کنید.
دستورالعمل برای پرس و جو و جهش
علاوه بر دستورالعملهایی که در تعریف انواع و جداول استفاده میکنید، Data Connect دستورات @auth
، @check
، @redact
و @transaction
را برای تقویت رفتار کوئریها و جهشها ارائه میکند.
بخشنامه | قابل اجرا برای | توضیحات |
---|---|---|
@auth | پرس و جو و جهش | خط مشی احراز هویت را برای یک پرس و جو یا جهش تعریف می کند. راهنمای مجوز و گواهینامه را ببینید. |
@check | درخواست جستجوی داده های مجوز | بررسی می کند که فیلدهای مشخص شده در نتایج پرس و جو وجود دارد. یک عبارت Common Expression Language (CEL) برای آزمایش مقادیر فیلد استفاده می شود. راهنمای مجوز و گواهینامه را ببینید. |
@redact | پرس و جوها | بخشی از پاسخ مشتری را ویرایش می کند. راهنمای مجوز و گواهینامه را ببینید. |
@transaction | جهش ها | الزام می کند که یک جهش همیشه در یک تراکنش پایگاه داده اجرا شود. نمونه های جهش برنامه فیلم را ببینید. |
پرس و جو برای پایگاه داده نقد و بررسی فیلم
شما یک کوئری Data Connect را با اعلان نوع عملیات پرس و جو، نام عملیات، آرگومان های عملیات صفر یا بیشتر، و صفر یا بیشتر دستورالعمل با آرگومان ها تعریف می کنید.
در شروع سریع، پرس و جوی مثال listEmails
هیچ پارامتری نداشت. البته در بسیاری از موارد داده های ارسال شده به فیلدهای پرس و جو پویا خواهند بود. میتوانید از نحو $variableName
برای کار با متغیرها بهعنوان یکی از اجزای تعریف پرسوجو استفاده کنید.
بنابراین پرس و جو زیر دارد:
- تعریف نوع
query
- نام عملیات
ListMoviesByGenre
(پرس و جو). - یک آرگومان عملیات
$genre
متغییر - یک دستورالعمل واحد،
@auth
.
query ListMoviesByGenre($genre: String!) @auth(level: USER)
هر آرگومان پرس و جو نیاز به یک اعلان نوع، یک نوع داخلی مانند String
، یا یک نوع سفارشی، طرحواره تعریف شده مانند Movie
دارد.
بیایید به امضای پرس و جوهای پیچیده تر نگاه کنیم. شما با معرفی عبارات ارتباطی قدرتمند و مختصر موجود در پرسوجوهای ضمنی که میتوانید در پرسوجوهای از پیش تعریفشده خود بر روی آنها بسازید، به پایان میرسید.
اسکالرهای کلیدی در پرس و جوها
اما ابتدا یک نکته در مورد اسکالرهای کلیدی.
Data Connect نوع خاصی را برای اسکالرهای کلیدی تعریف می کند که با _Key
مشخص می شود. به عنوان مثال، نوع اسکالر کلید برای جدول Movie
ما Movie_Key
است.
شما اسکالرهای کلیدی را به عنوان پاسخی که توسط اکثر جهشهای ضمنی برگردانده میشود، یا البته از کوئریهایی که تمام فیلدهای مورد نیاز برای ساختن کلید اسکالر را بازیابی کردهاید، بازیابی میکنید.
پرسوجوهای خودکار منفرد، مانند movie
در مثال در حال اجرا، از یک آرگومان کلیدی پشتیبانی میکنند که یک اسکالر کلیدی را میپذیرد.
شما ممکن است یک اسکالر کلیدی را به صورت تحت اللفظی پاس کنید. اما، می توانید متغیرهایی را برای ارسال اسکالرهای کلیدی به عنوان ورودی تعریف کنید.
query GetMovie($myKey: Movie_Key!) {
movie(key: $myKey) { title }
}
اینها را می توان در درخواست JSON مانند این (یا سایر قالب های سریال سازی) ارائه کرد:
{
# …
"variables": {
"myKey": {"foo": "some-string-value", "bar": 42}
}
}
به لطف تجزیه اسکالر سفارشی، یک Movie_Key
نیز می تواند با استفاده از نحو شی که ممکن است حاوی متغیرهایی باشد ساخته شود. این بیشتر زمانی مفید است که بخواهید به دلایلی اجزای جداگانه را به متغیرهای مختلف تقسیم کنید.
نام مستعار در پرس و جوها
Data Connect از نام مستعار GraphQL در کوئری ها پشتیبانی می کند. با نام مستعار، نام داده هایی را که در نتایج یک پرس و جو برگردانده می شوند، تغییر می دهید. یک کوئری Data Connect می تواند چندین فیلتر یا عملیات پرس و جوی دیگر را در یک درخواست کارآمد به سرور اعمال کند و به طور موثر چندین «پرس و جوی فرعی» را همزمان صادر کند. برای جلوگیری از تصادم نام در مجموعه داده های برگشتی، از نام مستعار برای تشخیص پرس و جوهای فرعی استفاده می کنید.
در اینجا یک جستجو وجود دارد که در آن یک عبارت از نام مستعار mostPopular
استفاده می کند.
query ReviewTopPopularity($genre: String) {
mostPopular: review(first: {
where: {genre: {eq: $genre}},
orderBy: {popularity: DESC}
}) { … }
}
پرس و جوهای ساده با فیلتر
پرس و جوهای Data Connect به تمام فیلترهای رایج SQL و عملیات سفارش نگاشت می شوند.
عملگرهای where
و orderBy
(پرسشهای مفرد، جمع)
تمام ردیف های منطبق از جدول (و پیوندهای تودرتو) را برمی گرداند. اگر هیچ رکوردی با فیلتر مطابقت نداشته باشد، آرایه خالی را برمیگرداند.
query MovieByTopRating($genre: String) {
mostPopular: movies(
where: { genre: { eq: $genre } }, orderBy: { rating: DESC }
) {
# graphql: list the fields from the results to return
id
title
genre
description
}
}
query MoviesByReleaseYear($min: Int, $max: Int) {
movies(where: {releaseYear: {le: $max, ge: $min}}, orderBy: [{releaseYear: ASC}]) { … }
}
عملگرهای limit
و offset
(پرس و جوهای مفرد، جمع)
می توانید صفحه بندی را روی نتایج انجام دهید. این آرگومانها پذیرفته میشوند اما به نتایج بازگردانده نمیشوند.
query MoviesTop10 {
movies(orderBy: [{ rating: DESC }], limit: 10) {
# graphql: list the fields from the results to return
title
}
}
شامل زمینه های آرایه می شود
می توانید آزمایش کنید که یک فیلد آرایه شامل یک آیتم مشخص شده باشد.
# Filter using arrays and embedded fields.
query ListMoviesByTag($tag: String!) {
movies(where: { tags: { includes: $tag }}) {
# graphql: list the fields from the results to return
id
title
}
}
عملیات رشته و عبارات منظم
جستارهای شما می توانند از عملیات جستجو و مقایسه رشته ای معمولی از جمله عبارات منظم استفاده کنند. توجه داشته باشید که برای کارایی شما چندین عملیات را در اینجا دسته بندی می کنید و آنها را با نام مستعار رفع می کنید.
query MoviesTitleSearch($prefix: String, $suffix: String, $contained: String, $regex: String) {
prefixed: movies(where: {title: {startsWith: $prefix}}) {...}
suffixed: movies(where: {title: {endsWith: $suffix}}) {...}
contained: movies(where: {title: {contains: $contained}}) {...}
matchRegex: movies(where: {title: {pattern: {regex: $regex}}}) {...}
}
or
و and
برای فیلترهای ترکیبی
or
و and
برای منطق پیچیده تر استفاده کنید.
query ListMoviesByGenreAndGenre($minRating: Int!, $genre: String) {
movies(
where: { _or: [{ rating: { ge: $minRating } }, { genre: { eq: $genre } }] }
) {
# graphql: list the fields from the results to return
title
}
}
پرس و جوهای پیچیده
کوئری های Data Connect می توانند به داده ها بر اساس روابط بین جداول دسترسی داشته باشند. شما می توانید از روابط شی (یک به یک) یا آرایه (یک به چند) تعریف شده در طرحواره خود برای ایجاد پرس و جوهای تودرتو، یعنی واکشی داده برای یک نوع به همراه داده های یک نوع تودرتو یا مرتبط استفاده کنید.
چنین پرس و جوهایی از جادویی Data Connect _on_
و _via
syntax در جستارهای ضمنی تولید شده استفاده می کنند.
شما تغییراتی در طرحواره از نسخه اولیه ما ایجاد خواهید کرد.
بسیاری به یک
بیایید نظرات را به برنامه خود اضافه کنیم، با جدول Review
و تغییراتی در User
.
# Users
# Suppose a user can leave reviews for movies
# user:reviews is a one to many relationship,
# movie:reviews is a one to many relationship,
# movie:user is a many to many relationship
type User
@table(name: "Users", singular: "user", plural: "users", key: ["id"]) {
id: UUID! @col(name: "user_id") @default(expr: "uuidV4()")
auth: String @col(name: "user_auth") @default(expr: "auth.uid")
username: String! @col(name: "username", dataType: "varchar(30)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
# Reviews
type Review @table(name: "Reviews", key: ["movie", "user"]) {
id: UUID! @col(name: "review_id") @default(expr: "uuidV4()")
user: User! @ref
movie: Movie! @ref
rating: Int
reviewText: String
reviewDate: Date! @default(expr: "request.time")
}
پرس و جو برای خیلی به یک
حالا بیایید به یک پرس و جو نگاه کنیم، با نام مستعار، برای نشان دادن نحو _via_
.
query UserMoviePreferences($username: String!) @auth(level: USER) {
users(where: { username: { eq: $username } }) {
likedMovies: movies_via_review(where: { rating: { ge: 4 } }) {
title
genre
description
}
dislikedMovies: movies_via_review(where: { rating: { le: 2 } }) {
title
genre
description
}
}
}
یک به یک
می توانید الگو را ببینید. در زیر، این طرح برای تصویر اصلاح شده است.
# Movies
type Movie
@table(name: "Movies", singular: "movie", plural: "movies", key: ["id"]) {
id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
title: String!
releaseYear: Int @col(name: "release_year")
genre: String
rating: Int @col(name: "rating")
description: String @col(name: "description")
tags: [String] @col(name: "tags")
}
# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata
@table(
name: "MovieMetadata"
) {
# @ref creates a field in the current table (MovieMetadata) that holds the primary key of the referenced type
# In this case, @ref(fields: "id") is implied
movie: Movie! @ref
# movieId: UUID <- this is created by the above @ref
director: String @col(name: "director")
}
extend type MovieMetadata {
movieId: UUID! # matches primary key of referenced type
...
}
extend type Movie {
movieMetadata: MovieMetadata # can only be non-nullable on ref side
# conflict-free name, always generated
movieMetadatas_on_movie: MovieMetadata
}
یک به یک پرس و جو کنید
می توانید با استفاده از نحو _on_
پرس و جو کنید.
# One to one
query GetMovieMetadata($id: UUID!) @auth(level: PUBLIC) {
movie(id: $id) {
movieMetadatas_on_movie {
director
}
}
}
خیلی به خیلی ها
فیلم ها به بازیگر نیاز دارند و بازیگران به فیلم. آنها روابط بسیار زیادی دارند که می توانید با جدول پیوستن MovieActors
مدل کنید.
# MovieActors Join Table Definition
type MovieActors @table(
key: ["movie", "actor"] # join key triggers many-to-many generation
) {
movie: Movie!
actor: Actor!
}
# generated extensions for the MovieActors join table
extend type MovieActors {
movieId: UUID!
actorId: UUID!
}
# Extensions for Actor and Movie to handle many-to-many relationships
extend type Movie {
movieActors: [MovieActors!]! # standard many-to-one relation to join table
actors: [Actor!]! # many-to-many via join table
movieActors_on_actor: [MovieActors!]!
# since MovieActors joins distinct types, type name alone is sufficiently precise
actors_via_MovieActors: [Actor!]!
}
extend type Actor {
movieActors: [MovieActors!]! # standard many-to-one relation to join table
movies: [Movie!]! # many-to-many via join table
movieActors_on_movie: [MovieActors!]!
movies_via_MovieActors: [Movie!]!
}
پرس و جو برای بسیاری از بسیاری
بیایید به یک پرس و جو با نام مستعار نگاه کنیم تا نحو _via_
را نشان دهیم.
query GetMovieCast($movieId: UUID!, $actorId: UUID!) @auth(level: PUBLIC) {
movie(id: $movieId) {
mainActors: actors_via_MovieActor(where: { role: { eq: "main" } }) {
name
}
supportingActors: actors_via_MovieActor(
where: { role: { eq: "supporting" } }
) {
name
}
}
actor(id: $actorId) {
mainRoles: movies_via_MovieActor(where: { role: { eq: "main" } }) {
title
}
supportingRoles: movies_via_MovieActor(
where: { role: { eq: "supporting" } }
) {
title
}
}
}
جهش برای پایگاه داده نقد فیلم
همانطور که گفته شد، زمانی که جدولی را در طرحواره خود تعریف می کنید، Data Connect جهش های ضمنی اساسی را برای هر جدول ایجاد می کند.
type Movie @table { ... }
extend type Mutation {
# Insert a row into the movie table.
movie_insert(...): Movie_Key!
# Upsert a row into movie."
movie_upsert(...): Movie_Key!
# Update a row in Movie. Returns null if a row with the specified id/key does not exist
movie_update(...): Movie_Key
# Update rows based on a filter in Movie.
movie_updateMany(...): Int!
# Delete a single row in Movie. Returns null if a row with the specified id/key does not exist
movie_delete(...): Movie_Key
# Delete rows based on a filter in Movie.
movie_deleteMany(...): Int!
}
با استفاده از این موارد، می توانید موارد پیچیده هسته ای CRUD را پیاده سازی کنید. پنج بار سریع بگو!
دستورالعمل @transaction
این دستورالعمل الزام می کند که یک جهش همیشه در یک تراکنش پایگاه داده اجرا شود.
جهش با @transaction
تضمین شده است که یا به طور کامل موفق شود یا به طور کامل شکست بخورد. اگر هر یک از فیلدهای داخل تراکنش از کار بیفتد، کل تراکنش برگردانده می شود. از نقطه نظر مشتری، هر شکست به گونه ای رفتار می کند که گویی کل درخواست با یک خطای درخواست شکست خورده است و اجرا آغاز نشده است.
جهش های بدون @transaction
هر فیلد ریشه را یکی پس از دیگری به ترتیب اجرا می کنند. هر گونه خطا را به عنوان خطای میدانی جزئی نشان می دهد، اما تاثیرات اجرای بعدی را نه.
ایجاد کنید
بیایید کارهای اساسی انجام دهیم.
# Create a movie based on user input
mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
movie_insert(data: {
title: $title
releaseYear: $releaseYear
genre: $genre
rating: $rating
})
}
# Create a movie with default values
mutation CreateMovie2 {
movie_insert(data: {
title: "Sherlock Holmes"
releaseYear: 2009
genre: "Mystery"
rating: 5
})
}
یا یک تاپیک
# Movie upsert using combination of variables and literals
mutation UpsertMovie($title: String!) {
movie_upsert(data: {
title: $title
releaseYear: 2009
genre: "Mystery"
rating: 5
genre: "Mystery/Thriller"
})
}
به روز رسانی را انجام دهید
در اینجا به روز رسانی است. تهیهکنندگان و کارگردانان مطمئناً امیدوارند که این رتبهبندیهای متوسط رو به رشد باشد.
mutation UpdateMovie(
$id: UUID!,
$genre: String!,
$rating: Int!,
$description: String!
) {
movie_update(id: $id, data: {
genre: $genre
rating: $rating
description: $description
})
}
# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $ratingIncrement: Int!) {
movie_updateMany(
where: { genre: { eq: $genre } },
update: { rating: { inc: $ratingIncrement } }
)
}
حذف ها را انجام دهید
البته می توانید داده های فیلم را حذف کنید. محافظان فیلم مطمئناً مایلند که فیلمهای فیزیکی تا زمانی که ممکن است نگهداری شوند.
# Delete by key
mutation DeleteMovie($id: UUID!) {
movie_delete(id: $id)
}
در اینجا می توانید از _deleteMany
استفاده کنید.
# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
movie_deleteMany(where: { rating: { le: $minRating } })
}
جهش را روی روابط بنویسید
نحوه استفاده از جهش _upsert
ضمنی را در یک رابطه مشاهده کنید.
# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
movieMetadata_upsert(
data: { movie: { id: $movieId }, director: $director }
)
}
درخواست جستجوی داده های مجوز
جهش های Data Connect را می توان با پرس و جو در پایگاه داده و تأیید نتایج پرس و جو با عبارات CEL مجاز کرد. این زمانی مفید است که در حال نوشتن روی یک جدول هستید و باید محتویات یک ردیف را در جدول دیگری بررسی کنید.
این ویژگی پشتیبانی می کند:
- دستورالعمل
@check
، که به شما امکان میدهد محتویات فیلدها را ارزیابی کنید و بر اساس نتایج چنین ارزیابی:- ایجاد، به روز رسانی و حذف های تعریف شده توسط جهش را ادامه دهید
- از مقادیری که توسط پرس و جو به مشتریان بازگردانده می شود برای اجرای منطق متفاوت در مشتریان خود استفاده کنید
- دستورالعمل
@redact
، که به شما امکان می دهد نتایج پرس و جو را از نتایج پروتکل سیمی حذف کنید.
این ویژگی ها برای جریان های مجوز مفید هستند.
طرحواره SQL معادل
-- Movies Table
CREATE TABLE Movies (
movie_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
title VARCHAR(255) NOT NULL,
release_year INT,
genre VARCHAR(30),
rating INT,
description TEXT,
tags TEXT[]
);
-- Movie Metadata Table
CREATE TABLE MovieMetadata (
movie_id UUID REFERENCES Movies(movie_id) UNIQUE,
director VARCHAR(255) NOT NULL,
PRIMARY KEY (movie_id)
);
-- Actors Table
CREATE TABLE Actors (
actor_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(30) NOT NULL
);
-- MovieActor Join Table for Many-to-Many Relationship
CREATE TABLE MovieActor (
movie_id UUID REFERENCES Movies(movie_id),
actor_id UUID REFERENCES Actors(actor_id),
role VARCHAR(50) NOT NULL, # "main" or "supporting"
PRIMARY KEY (movie_id, actor_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id),
FOREIGN KEY (actor_id) REFERENCES Actors(actor_id)
);
-- Users Table
CREATE TABLE Users (
user_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_auth VARCHAR(255) NOT NULL
username VARCHAR(30) NOT NULL
);
-- Reviews Table
CREATE TABLE Reviews (
review_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES Users(user_id),
movie_id UUID REFERENCES Movies(movie_id),
rating INT,
review_text TEXT,
review_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (movie_id, user_id)
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
-- Self Join Example for Movie Sequel Relationship
ALTER TABLE Movies
ADD COLUMN sequel_to UUID REFERENCES Movies(movie_id);
بعدش چی؟
- بیاموزید که چگونه پرس و جوها و جهش های خود را با مجوز و گواهی ایمن کنید.
- با نحوه فراخوانی پرسشها و جهشهای خود از یک وب SDK ، Android SDK ، iOS SDK و Flutter SDK که بهطور خودکار ایجاد میشود، بیاموزید.