Giản đồ, truy vấn và dữ liệu đột biến của Data Connect

Firebase Data Connect cho phép bạn tạo trình kết nối cho các phiên bản PostgreSQL được quản lý bằng Google Cloud SQL. Các trình kết nối này là sự kết hợp của một giản đồ, truy vấn và đột biến để sử dụng dữ liệu của bạn.

Hướng dẫn bắt đầu đã giới thiệu giản đồ ứng dụng đánh giá phim cho PostgreSQL và hướng dẫn này sẽ xem xét kỹ hơn về cách thiết kế giản đồ Data Connect cho PostgreSQL.

Hướng dẫn này sẽ ghép nối các truy vấn và đột biến Data Connect với các ví dụ về giản đồ. Tại sao chúng ta lại thảo luận về truy vấn (và sự thay đổi) trong hướng dẫn về schema Data Connect? Giống như các nền tảng dựa trên GraphQL khác, Firebase Data Connect là một nền tảng phát triển ưu tiên truy vấn. Vì vậy, với tư cách là nhà phát triển, trong quá trình lập mô hình dữ liệu, bạn sẽ phải suy nghĩ về dữ liệu mà khách hàng của mình cần. Điều này sẽ ảnh hưởng rất lớn đến giản đồ dữ liệu mà bạn phát triển cho dự án của mình.

Hướng dẫn này bắt đầu bằng một giản đồ mới cho bài đánh giá phim, sau đó trình bày về truy vấnsự thay đổi bắt nguồn từ giản đồ đó, cuối cùng cung cấp danh sách SQL tương đương với giản đồ Data Connect cốt lõi.

Sơ đồ cho ứng dụng đánh giá phim

Giả sử bạn muốn xây dựng một dịch vụ cho phép người dùng gửi và xem bài đánh giá phim.

Bạn cần có một giản đồ ban đầu cho ứng dụng như vậy. Bạn sẽ mở rộng giản đồ này sau đó để tạo các truy vấn quan hệ phức tạp.

Bảng phim

Giản đồ cho Phim chứa các lệnh chính như:

  • @table, cho phép chúng ta đặt tên cho toán tử bằng cách sử dụng đối số singularplural
  • @col để đặt tên cột một cách rõ ràng
  • @default để cho phép đặt giá trị mặc định.
# 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")
}

Giá trị máy chủ và đại lượng vô hướng khoá

Trước khi xem xét ứng dụng đánh giá phim, hãy giới thiệu Data Connect giá trị máy chủgiá trị vô hướng chính.

Khi sử dụng giá trị máy chủ, bạn có thể cho phép máy chủ tự động điền các trường trong bảng bằng cách sử dụng các giá trị đã lưu trữ hoặc dễ dàng tính toán theo các biểu thức cụ thể phía máy chủ. Ví dụ: bạn có thể xác định một trường có dấu thời gian được áp dụng khi truy cập vào trường đó bằng biểu thức updatedAt: Timestamp! @default(expr: "request.time").

Đại lượng vô hướng chính là giá trị nhận dạng đối tượng ngắn gọn mà Data Connect tự động ghép nối từ các trường chính trong giản đồ. Số thực đơn biến là về hiệu quả, cho phép bạn tìm thấy trong một lệnh gọi thông tin về danh tính và cấu trúc của dữ liệu. Các khoá này đặc biệt hữu ích khi bạn muốn thực hiện các thao tác tuần tự trên các bản ghi mới và cần một giá trị nhận dạng duy nhất để truyền đến các thao tác sắp tới, cũng như khi bạn muốn truy cập vào các khoá quan hệ để thực hiện các thao tác phức tạp hơn.

Bảng siêu dữ liệu của phim

Bây giờ, hãy theo dõi các đạo diễn phim, cũng như thiết lập mối quan hệ một với một với Movie.

Thêm lệnh @ref để xác định mối quan hệ.

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

Actor và MovieActor

Tiếp theo, bạn muốn các diễn viên đóng vai chính trong phim của mình. Vì bạn có mối quan hệ nhiều với nhiều giữa phim và diễn viên, hãy tạo một bảng nối.

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

Người dùng

Cuối cùng, người dùng ứng dụng của bạn.

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

Loại dữ liệu được hỗ trợ

Data Connect hỗ trợ các loại dữ liệu vô hướng sau đây, với các giá trị gán cho các loại PostgreSQL bằng @col(dataType:).

Loại Data Connect Loại tích hợp sẵn GraphQL hoặc loại tuỳ chỉnh
Data Connect
Loại PostgreSQL mặc định Các loại PostgreSQL được hỗ trợ
(bí danh trong ngoặc đơn)
Chuỗi GraphQL văn bản text
bit(n), varbit(n)
char(n), varchar(n)
Int GraphQL int Int2 (smallint, smallserial),
int4 (integer, int, serial)
Nổi GraphQL float8 float4 (thực)
float8 (độ chính xác kép)
số (thập phân)
Boolean GraphQL boolean boolean
mã nhận dạng duy nhất (UUID) Tuỳ chỉnh uuid uuid
Int64 Tuỳ chỉnh bigint int8 (bigint, bigserial)
số (thập phân)
Ngày Tuỳ chỉnh ngày ngày
Dấu thời gian Tuỳ chỉnh timestamptz

timestamptz

Lưu ý: Thông tin về múi giờ tại địa phương không được lưu trữ.
PostgreSQL chuyển đổi và lưu trữ các dấu thời gian đó dưới dạng UTC.

Vectơ Tuỳ chỉnh vector

vectơ

Xem bài viết Tìm kiếm độ tương đồng vectơ bằng Vertex AI.

  • GraphQL List liên kết đến một mảng một chiều.
    • Ví dụ: [Int] liên kết đến int5[], [Any] liên kết đến jsonb[].
    • Data Connect không hỗ trợ mảng lồng nhau.

Các truy vấn và đột biến ngầm ẩn và được xác định trước

Các truy vấn và đột biến Data Connect sẽ mở rộng một tập hợp truy vấn ngầm ẩnđột biến ngầm ẩn do Data Connect tạo ra dựa trên các loại và mối quan hệ loại trong giản đồ. Các truy vấn và đột biến ngầm ẩn được tạo bằng công cụ cục bộ bất cứ khi nào bạn chỉnh sửa giản đồ.

Trong quá trình phát triển, bạn sẽ triển khai các truy vấn được xác định trướccác đột biến được xác định trước dựa trên các thao tác ngầm ẩn này.

Tên truy vấn và đột biến ngầm ẩn

Data Connect suy luận tên phù hợp cho các truy vấn và đột biến ngầm ẩn từ nội dung khai báo loại giản đồ. Ví dụ: khi làm việc với nguồn PostgreSQL, nếu bạn xác định một bảng có tên là Movie, máy chủ sẽ tạo ngầm ẩn:

  • Truy vấn cho các trường hợp sử dụng bảng đơn có tên thân thiện movie (số ít, để truy xuất kết quả riêng lẻ truyền các đối số như eq) và movies (số nhiều, để truy xuất danh sách kết quả truyền các đối số như gt và các thao tác như orderby). Data Connect cũng tạo truy vấn cho các thao tác liên quan nhiều bảng có tên rõ ràng như actors_on_movies hoặc actors_via_actormovie.
  • Các đột biến có tên movie_insert, movie_upsert...

Ngôn ngữ định nghĩa giản đồ cũng cho phép bạn đặt tên rõ ràng cho các thao tác bằng cách sử dụng đối số lệnh singularplural.

Chỉ thị cho truy vấn và đột biến

Ngoài các lệnh mà bạn sử dụng để xác định loại và bảng, Data Connect còn cung cấp các lệnh @auth, @check, @redact@transaction để tăng cường hành vi của truy vấn và đột biến.

Chỉ thị Áp dụng cho Nội dung mô tả
@auth Truy vấn và đột biến Xác định chính sách xác thực cho một truy vấn hoặc đột biến. Xem hướng dẫn uỷ quyền và chứng thực.
@check Truy vấn tra cứu dữ liệu uỷ quyền Xác minh rằng các trường được chỉ định có trong kết quả truy vấn. Biểu thức Ngôn ngữ diễn đạt thông thường (CEL) được dùng để kiểm thử giá trị trường. Xem hướng dẫn uỷ quyền và chứng thực.
@redact Cụm từ tìm kiếm Xoá một phần nội dung phản hồi của ứng dụng khách. Xem hướng dẫn uỷ quyền và chứng thực.
@transaction Đột biến Thực thi để một đột biến luôn chạy trong một giao dịch cơ sở dữ liệu. Xem ví dụ về đột biến ứng dụng phim.

Truy vấn cho cơ sở dữ liệu bài đánh giá phim

Bạn xác định truy vấn Data Connect bằng cách khai báo loại thao tác truy vấn, tên thao tác, không có hoặc có đối số thao tác và không có hoặc có lệnh có đối số.

Trong phần hướng dẫn nhanh, truy vấn listEmails mẫu không có tham số nào. Tất nhiên, trong nhiều trường hợp, dữ liệu được truyền đến các trường truy vấn sẽ mang tính động. Bạn có thể sử dụng cú pháp $variableName để xử lý các biến dưới dạng một trong các thành phần của định nghĩa truy vấn.

Vì vậy, truy vấn sau đây có:

  • Định nghĩa kiểu query
  • Tên toán tử (truy vấn) ListMoviesByGenre
  • Một đối số toán tử $genre biến
  • Một lệnh duy nhất, @auth.
query ListMoviesByGenre($genre: String!) @auth(level: USER)

Mỗi đối số truy vấn đều yêu cầu một nội dung khai báo kiểu, một nội dung tích hợp sẵn như String hoặc một kiểu tuỳ chỉnh, do giản đồ xác định như Movie.

Hãy xem chữ ký của các truy vấn ngày càng phức tạp. Bạn sẽ kết thúc bằng cách giới thiệu các biểu thức mối quan hệ mạnh mẽ, súc tích có trong các truy vấn ngầm ẩn mà bạn có thể xây dựng trong các truy vấn được xác định trước.

Số thực chính trong truy vấn

Nhưng trước tiên, hãy lưu ý về đại lượng vô hướng chính.

Data Connect xác định một loại đặc biệt cho các đại lượng vô hướng chính, được xác định bằng _Key. Ví dụ: loại của một đại lượng vô hướng khoá cho bảng MovieMovie_Key.

Bạn truy xuất các đại lượng vô hướng chính dưới dạng phản hồi do hầu hết các đột biến ngầm ẩn trả về, hoặc tất nhiên là từ các truy vấn mà bạn đã truy xuất tất cả các trường cần thiết để tạo khoá vô hướng.

Các truy vấn tự động số ít, chẳng hạn như movie trong ví dụ đang chạy, hỗ trợ đối số khoá chấp nhận một đại lượng vô hướng khoá.

Bạn có thể truyền một đại lượng vô hướng khoá dưới dạng giá trị cố định. Tuy nhiên, bạn có thể xác định các biến để truyền các đại lượng vô hướng khoá làm dữ liệu đầu vào.

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

Bạn có thể cung cấp các thông tin này trong yêu cầu JSON như sau (hoặc các định dạng chuyển đổi tuần tự khác):

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

Nhờ khả năng phân tích cú pháp vô hướng tuỳ chỉnh, bạn cũng có thể tạo Movie_Key bằng cách sử dụng cú pháp đối tượng có thể chứa các biến. Điều này chủ yếu hữu ích khi bạn muốn chia các thành phần riêng lẻ thành các biến khác nhau vì lý do nào đó.

Bí danh trong truy vấn

Data Connect hỗ trợ việc gán bí danh GraphQL trong các truy vấn. Với bí danh, bạn đổi tên dữ liệu được trả về trong kết quả của truy vấn. Một truy vấn Data Connect có thể áp dụng nhiều bộ lọc hoặc các thao tác truy vấn khác trong một yêu cầu hiệu quả đến máy chủ, đồng thời phát hành một số "truy vấn phụ" một cách hiệu quả. Để tránh xung đột tên trong tập dữ liệu được trả về, bạn sử dụng bí danh để phân biệt các truy vấn phụ.

Dưới đây là một truy vấn trong đó biểu thức sử dụng bí danh mostPopular.

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

Truy vấn đơn giản có bộ lọc

Truy vấn Data Connect liên kết đến tất cả bộ lọc SQL và thao tác thứ tự phổ biến.

Toán tử whereorderBy (truy vấn số ít, số nhiều)

Trả về tất cả các hàng đã so khớp trong bảng (và các mối liên kết lồng nhau). Trả về một mảng trống nếu không có bản ghi nào khớp với bộ lọc.

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}]) {  }
}

Toán tử limitoffset (truy vấn số ít, số nhiều)

Bạn có thể phân trang kết quả. Các đối số này được chấp nhận nhưng không được trả về trong kết quả.

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

bao gồm các trường mảng

Bạn có thể kiểm tra để đảm bảo rằng một trường mảng chứa một mục đã chỉ định.

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

Thao tác với chuỗi và biểu thức chính quy

Truy vấn của bạn có thể sử dụng các thao tác so sánh và tìm kiếm chuỗi thông thường, bao gồm cả biểu thức chính quy. Lưu ý để tăng hiệu quả, bạn đang gộp một số thao tác ở đây và phân biệt các thao tác đó bằng bí danh.

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}}}) {...}
}

orand cho bộ lọc tổng hợp

Sử dụng orand cho logic phức tạp hơn.

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

Câu lệnh truy vấn phức tạp

Truy vấn Data Connect có thể truy cập dữ liệu dựa trên mối quan hệ giữa các bảng. Bạn có thể sử dụng mối quan hệ đối tượng (một với một) hoặc mảng (một với nhiều) được xác định trong giản đồ để tạo truy vấn lồng nhau, tức là tìm nạp dữ liệu cho một loại cùng với dữ liệu từ một loại lồng nhau hoặc có liên quan.

Các truy vấn như vậy sử dụng cú pháp Data Connect _on__via ma thuật trong các truy vấn ngầm được tạo.

Bạn sẽ sửa đổi giản đồ từ phiên bản ban đầu của chúng tôi.

Nhiều với một

Hãy thêm bài đánh giá vào ứng dụng của chúng ta, với bảng Review và các sửa đổi đối với 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")
}

Truy vấn nhiều với một

Bây giờ, hãy xem một truy vấn có sử dụng bí danh để minh hoạ cú pháp _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
    }
  }
}

Một với một

Bạn có thể thấy mẫu này. Dưới đây là giản đồ được sửa đổi để minh hoạ.

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

Truy vấn một với một

Bạn có thể truy vấn bằng cú pháp _on_.

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

Nhiều với nhiều

Phim cần diễn viên và diễn viên cần phim. Các thành phần này có mối quan hệ nhiều với nhiều mà bạn có thể lập mô hình bằng bảng nối 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!]!
}

Truy vấn nhiều với nhiều

Hãy xem một truy vấn có sử dụng bí danh để minh hoạ cú pháp _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
    }
  }
}

Các đột biến cho cơ sở dữ liệu bài đánh giá phim

Như đã đề cập, khi bạn xác định một bảng trong giản đồ, Data Connect sẽ tạo các đột biến ngầm ẩn cơ bản cho mỗi bảng.

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

Với những kiến thức này, bạn có thể triển khai các trường hợp CRUD cốt lõi ngày càng phức tạp. Hãy nói nhanh năm lần!

Chỉ thị @transaction

Chỉ thị này thực thi việc một đột biến luôn chạy trong một giao dịch cơ sở dữ liệu.

Các đột biến với @transaction được đảm bảo sẽ thành công hoàn toàn hoặc không thành công hoàn toàn. Nếu có trường nào trong giao dịch không thành công, toàn bộ giao dịch sẽ được hoàn tác. Từ quan điểm của máy khách, mọi lỗi đều hoạt động như thể toàn bộ yêu cầu đã không thành công do lỗi yêu cầu và quá trình thực thi chưa bắt đầu.

Các đột biến không có @transaction sẽ thực thi từng trường gốc theo trình tự. Lỗi này hiển thị dưới dạng lỗi trường một phần, nhưng không phải là tác động của các lần thực thi tiếp theo.

Tạo

Hãy tạo các thành phần cơ bản.

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

Hoặc một thao tác chèn mới.

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

Thực hiện cập nhật

Sau đây là thông tin cập nhật. Nhà sản xuất và đạo diễn chắc chắn hy vọng những điểm xếp hạng trung bình đó sẽ tăng lên.

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

Thực hiện xoá

Tất nhiên, bạn có thể xoá dữ liệu phim. Những người bảo tồn phim chắc chắn sẽ muốn duy trì phim vật lý lâu nhất có thể.

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

Tại đây, bạn có thể sử dụng _deleteMany.

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

Viết các đột biến trên mối quan hệ

Quan sát cách sử dụng đột biến _upsert ngầm ẩn trên một mối quan hệ.

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

Truy vấn tra cứu dữ liệu uỷ quyền

Bạn có thể uỷ quyền cho các đột biến Data Connect bằng cách truy vấn cơ sở dữ liệu và xác minh kết quả của truy vấn bằng biểu thức CEL. Điều này rất hữu ích khi bạn đang ghi vào một bảng và cần kiểm tra nội dung của một hàng trong một bảng khác.

Tính năng này hỗ trợ:

  • Lệnh @check cho phép bạn đánh giá nội dung của các trường và dựa trên kết quả của quá trình đánh giá đó:
    • Tiếp tục tạo, cập nhật và xoá do đột biến xác định
    • Sử dụng các giá trị do truy vấn trả về cho ứng dụng để thực hiện nhiều logic khác nhau trong ứng dụng
  • Lệnh @redact cho phép bạn bỏ qua kết quả truy vấn khỏi kết quả giao thức truyền dẫn.

Các tính năng này hữu ích cho quy trình uỷ quyền.

Sơ đồ SQL tương đương

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

Tiếp theo là gì?