SQL Connect mutasyonlarını uygulama

Firebase SQL Connect, Cloud SQL ile yönetilen PostgreSQL örnekleriniz için bağlayıcılar oluşturmanıza olanak tanır. Bu bağlayıcılar, şemanızdaki verilerinizi kullanmak için sorgu ve mutasyonların birleşimidir.

Başlangıç kılavuzunda PostgreSQL için bir film inceleme uygulaması şeması tanıtıldı.

Bu kılavuzda, değişiklikler de dahil olmak üzere hem dağıtılabilir hem de geçici yönetim işlemleri tanıtılmıştı.

  • Dağıtılabilir mutasyonlar, tanımladığınız API uç noktalarıyla bir bağlayıcıdaki istemci uygulamalarından çağrı yapmak için uyguladığınız mutasyonlardır. SQL Connect, kimlik doğrulama ve yetkilendirmeyi bu mutasyonlara entegre eder ve API'nize dayalı istemci SDK'ları oluşturur.
  • Geçici yönetim mutasyonları, tabloları doldurmak ve yönetmek için ayrıcalıklı ortamlarda çalıştırılır. Bu sorguları Firebase konsolunda, Firebase Admin SDK kullanarak ayrıcalıklı ortamlarda ve SQL Connect VS Code uzantımızı kullanarak yerel geliştirme ortamlarında oluşturup yürütebilirsiniz.

Bu kılavuzda, dağıtılabilir mutasyonlar daha ayrıntılı bir şekilde ele alınmaktadır.

SQL Connect mutasyonlarının özellikleri

SQL Connect, PostgreSQL veritabanı göz önüne alındığında bekleyeceğiniz tüm yöntemlerle temel mutasyonlar gerçekleştirmenize olanak tanır:

  • CRUD işlemleri gerçekleştirme
  • İşlemlerle çok adımlı işlemleri yönetme

Ancak SQL Connect'ın GraphQL'e yönelik uzantılarıyla daha hızlı ve verimli uygulamalar için gelişmiş mutasyonlar uygulayabilirsiniz:

  • Kayıtlar üzerinde tekrarlanan işlemleri basitleştirmek için birçok işlem tarafından döndürülen anahtar ölçeklendirme faktörlerini kullanın.
  • Verileri sunucu tarafından sağlanan işlemlerle doldurmak için sunucu değerlerini kullanın.
  • Verileri aramak için çok adımlı değişiklik işlemleri sırasında sorgular gerçekleştirerek kod satırlarını ve sunucuya gidiş dönüşleri azaltın.

Mutasyonları uygulamak için oluşturulan alanları kullanma

SQL Connect işlemleriniz, şemanızdaki türlere ve tür ilişkilerine göre SQL Connect tarafından otomatik olarak oluşturulan bir dizi alanı genişletir. Bu alanlar, şemanızı her düzenlediğinizde yerel araçlar tarafından oluşturulur.

Oluşturulan alanları, tek tablolardaki tek kayıtları oluşturma, güncelleme ve silme işlemlerinden daha karmaşık çok tablolu güncellemelere kadar mutasyonları uygulamak için kullanabilirsiniz.

Şemanızın bir Movie türü ve ilişkili bir Actor türü içerdiğini varsayalım. SQL Connect, movie_insert, movie_update, movie_delete alanlarını ve daha fazlasını oluşturur.


movie_insert alanı ile mutasyon

movie_insert alanı, Movie tablosunda tek bir kayıt oluşturmak için yapılan bir değişikliği temsil eder.

Tek bir film oluşturmak için bu alanı kullanın.

mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
  movie_insert(data: {
    title: $title
    releaseYear: $releaseYear
    genre: $genre
    rating: $rating
  })
}


movie_update alanı ile değişiklik

movie_update alanı, Movie tablosundaki tek bir kaydı güncellemek için yapılan bir değişikliği temsil eder.

Tek bir filmi anahtarına göre güncellemek için bu alanı kullanın.

mutation UpdateMovie($myKey: Movie_Key!, $genre: String, $rating: Int, $description: String) {
  movie_update(key: $myKey, data: {
    genre: $genre
    rating: $rating
    description: $description
  })
}


movie_delete alanı ile mutasyon

movie_delete alanı, Movie tablosunda tek bir kaydı silmeye yönelik bir değişikliği temsil eder.

Tek bir filmi anahtarına göre silmek için bu alanı kullanın.

  mutation DeleteMovie($myKey: Movie_Key!) {
    movie_delete(key: $myKey) { key }
  }

Mutasyonun temel unsurları

SQL Connect değişiklikleri, SQL Connect uzantıları olan GraphQL değişiklikleridir. Normal bir GraphQL mutasyonunda olduğu gibi, bir işlem adı ve GraphQL değişkenlerinin listesini tanımlayabilirsiniz.

SQL Connect, GraphQL sorgularını @auth ve @transaction gibi özelleştirilmiş yönergelerle genişletir.

Bu nedenle, aşağıdaki değişiklik şunları içerir:

  • mutation türü tanımı
  • Bir SignUp işlem (değişiklik) adı
  • Tek değişkenli $username işlem bağımsız değişkeni
  • Tek bir yönerge, @auth
  • Tek bir alan user_insert.
mutation SignUp($username: String!) @auth(level: USER) {
  user_insert(data: {
    id_expr: "auth.uid"
    username: $username
  })
}

Her mutasyon bağımsız değişkeni için bir tür bildirimi (String gibi yerleşik bir tür veya Movie gibi şemada tanımlanmış özel bir tür) gerekir.

Temel mutasyonları yazma

Veritabanınızdaki kayıtları tek tek oluşturmak, güncellemek ve silmek için mutasyon yazmaya başlayabilirsiniz.

Oluştur

Temel oluşturma işlemlerini yapalım.

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

Veya upsert işlemi.

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

Güncelleme yapma

Güncellemeler Yapımcılar ve yönetmenler, ortalama puanların bu trende uygun olmasını umar.

movie_update alanı, bir kaydı tanımlamak için beklenen bir id bağımsız değişkenini ve bu güncellemede değerleri ayarlamak için kullanabileceğiniz bir data alanını içerir.

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

Birden fazla güncelleme yapmak için movie_updateMany alanını kullanın.

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

_update ile artırma, azaltma, ekleme ve öne ekleme işlemlerini kullanma

_update ve _updateMany mutasyonlarında data: içinde değerleri açıkça ayarlayabilirsiniz ancak değerleri güncellemek için artırma gibi bir operatör uygulamak genellikle daha mantıklıdır.

Önceki güncelleme örneğini değiştirmek için belirli bir filmin derecelendirmesini artırmak istediğinizi varsayalım. rating_update söz dizimini inc operatörüyle birlikte kullanabilirsiniz.

mutation UpdateMovie(
  $id: UUID!,
  $ratingIncrement: Int!
) {
  movie_update(id: $id, data: {
    rating_update: {
      inc: $ratingIncrement
    }
  })
}

SQL Connect, alan güncellemeleri için aşağıdaki operatörleri destekler:

  • Int, Int64, Float, Date ve Timestamp veri türlerini artırmak için inc
  • dec, Int, Int64, Float, Date ve Timestamp veri türlerini azaltmak için

Listeler için aşağıdaki yöntemleri kullanarak tek tek değerlerle veya değer listeleriyle de güncelleme yapabilirsiniz:

  • Öğeler, Vektör listeleri hariç liste türlerinde mevcut değilse öğeleri eklemek için add
  • Vektör listeleri hariç olmak üzere tüm öğeleri liste türlerinden kaldırmak için remove
  • append(Vektör listeleri hariç) öğeleri liste türlerine eklemek için
  • prepend, öğeleri vektör listeleri hariç liste türlerine eklemek için

Silme işlemlerini gerçekleştirme

Elbette film verilerini silebilirsiniz. Film koruma uzmanları, fiziksel filmlerin mümkün olduğunca uzun süre korunmasını ister.

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

Burada _deleteMany kullanabilirsiniz.

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

İlişkilerde değişiklik yazma

Bir ilişkide örtülü _upsert mutasyonunun nasıl kullanılacağını gözlemleyin.

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

Verimli mutasyonlar için şemalar tasarlama

SQL Connect, daha verimli mutasyonlar yazmanıza ve gidiş-dönüş işlemlerinden tasarruf etmenize olanak tanıyan iki önemli özellik sunar.

Anahtar skalerler, şemalarınızdaki anahtar alanlardan SQL Connectotomatik olarak oluşturulan kısa nesne tanımlayıcılarıdır. Temel ölçekler, verilerinizin kimliği ve yapısı hakkında tek bir çağrıda bilgi bulmanıza olanak tanıyarak verimlilikle ilgilidir. Bu işlevler, özellikle yeni kayıtlarda sıralı işlemler gerçekleştirmek istediğinizde ve yaklaşan işlemlere aktarılacak benzersiz bir tanımlayıcıya ihtiyaç duyduğunuzda, ayrıca ek ve daha karmaşık işlemler gerçekleştirmek için ilişkisel anahtarlara erişmek istediğinizde kullanışlıdır.

Sunucu değerlerini kullanarak, sunucunun expr bağımsız değişkenindeki belirli sunucu tarafı CEL ifadelerine göre tablolarınızdaki alanları depolanmış veya kolayca hesaplanabilir değerlerle dinamik olarak doldurmasına etkili bir şekilde izin verebilirsiniz. Örneğin, bir işlem isteğinde depolanan zaman (updatedAt: Timestamp! @default(expr: "request.time")) kullanılarak alana erişildiğinde zaman damgası uygulanan bir alan tanımlayabilirsiniz.

Gelişmiş değişiklikler yazma: SQL Connect, field_expr söz dizimini kullanarak değerler sağlasın

Temel ölçekler ve sunucu değerleri bölümünde açıklandığı gibi, şemanızı, sunucunun istemci isteklerine yanıt olarak id ve tarihler gibi ortak alanların değerlerini dolduracak şekilde tasarlayabilirsiniz.

Ayrıca, istemci uygulamalarından gönderilen SQL Connect request nesnelerindeki kullanıcı kimlikleri gibi verilerden de yararlanabilirsiniz.

Değişiklikleri uygularken sunucu tarafından oluşturulan güncellemeleri tetiklemek veya isteklerden gelen verilere erişmek için field_expr söz dizimini kullanın. Örneğin, bir istekte depolanan uid yetkilendirmesini bir _upsert işlemine iletmek için userId_expr alanında "auth.uid" değerini iletin.

# Add a movie to the user's favorites list
mutation AddFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie_upsert(data: { userId_expr: "auth.uid", movieId: $movieId })
}

# Remove a movie from the user's favorites list
mutation DeleteFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
}

Alternatif olarak, alışkın olduğunuz bir yapılacaklar listesi uygulamasında yeni bir yapılacaklar listesi oluştururken id_expr ileterek sunucuya liste için otomatik olarak bir UUID oluşturma talimatı verebilirsiniz.

mutation CreateTodoListWithFirstItem(
  $listName: String!
) @transaction {
  # Step 1
  todoList_insert(data: {
    id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
    name: $listName,
  })
}

Daha fazla bilgi için skaler referansındaki _Expr skalerlerine bakın.

Gelişmiş değişiklikler yazma: çok adımlı işlemler

Tek bir değişiklikte birden fazla yazma alanı (ör. eklemeler) eklemek isteyebileceğiniz birçok durum vardır. Ayrıca, örneğin ekleme veya güncelleme işlemleri gerçekleştirmeden önce mevcut verileri aramak ve doğrulamak için mutasyon yürütülürken veritabanınızı okumak da isteyebilirsiniz. Bu seçenekler, gidiş dönüş işlemlerini ve dolayısıyla maliyetleri azaltır.

SQL Connect, aşağıdakileri destekleyerek mutasyonlarınızda çok adımlı mantık işlemleri yapmanıza olanak tanır:

  • Birden fazla yazma alanı

  • Mutasyonlarınızda birden fazla okuma alanı (query alan anahtar kelimesini kullanarak).

  • İlişkisel veritabanlarından tanıdık işlem desteği sağlayan @transaction yönergesi.

  • Okuma içeriklerini CEL ifadelerini kullanarak değerlendirmenize ve bu değerlendirmenin sonuçlarına göre işlem yapmanıza olanak tanıyan @check yönergesi:

    • Bir mutasyon tarafından tanımlanan oluşturma, güncelleme ve silme işlemlerine devam etme
    • Sorgu alanının sonuçlarını döndürmeye devam etme
    • İstemci kodunuzda uygun mantığı uygulamak için döndürülen mesajları kullanın.
  • @redact yönergesi, sorgu alanı sonuçlarını kablolu protokol sonuçlarından çıkarmanıza olanak tanır.

  • Karmaşık ve çok adımlı bir işlemde gerçekleştirilen tüm mutasyonların ve sorguların birikmiş sonuçlarını depolayan CEL response bağlaması. response bağlamasına erişebilirsiniz:

    • @check yönergelerinde, expr: bağımsız değişkeni aracılığıyla
    • field_expr söz dizimi kullanılarak sunucu değerleriyle

@transaction yönergesi

Çok adımlı değişiklikler için destek, işlemleri kullanarak hata işlemeyi içerir.

@transaction yönergesi, tek bir yazma alanı (örneğin, _insert veya _update) ya da birden fazla yazma alanı içeren bir mutasyonun her zaman bir veritabanı işleminde çalışmasını zorunlu kılar.

  • @transaction içermeyen mutasyonlar, her kök alanı sırayla birbiri ardına yürütür. İşlem, hataları kısmi alan hataları olarak gösterir ancak sonraki yürütmelerin etkilerini göstermez.

  • @transaction içeren mutasyonların tamamen başarılı veya tamamen başarısız olacağı garanti edilir. İşlemdeki alanlardan herhangi biri başarısız olursa tüm işlem geri alınır.

@check ve @redact yönergeleri

@check yönergesi, belirtilen alanların sorgu sonuçlarında bulunduğunu doğrular. Alan değerlerini test etmek için Common Expression Language (CEL) ifadesi kullanılır. Yönergenin varsayılan davranışı, değeri null veya [] (boş listeler) olan düğümleri kontrol edip reddetmektir.

@redact yönergesi, istemciden gelen yanıttaki bir bölümü çıkarır. Çıkarılan alanlar, yan etkiler (veri değişiklikleri ve @check dahil) açısından değerlendirilmeye devam eder ve sonuçlar, CEL ifadelerindeki sonraki adımlarda kullanılabilir.

@check, @check(message:) ve @redact özelliğini kullanın

@check ve @redact'nin temel kullanım alanlarından biri, belirli işlemlerin yetkilendirilip yetkilendirilmeyeceğine karar vermek için ilgili verileri aramak, mantıktaki aramayı kullanmak ancak istemcilerden gizlemektir. Sorgunuz, istemci kodunda doğru şekilde işlenmesi için yararlı mesajlar döndürebilir.

query GetMovieEditors($movieId: UUID!) @auth(level: USER) {
  moviePermission(key: { movieId: $movieId, userId_expr: "auth.uid" }) @redact {
    role @check(expr: "this == 'admin'", message: "You must be an admin to view all editors of a movie.")
  }
  moviePermissions(where: { movieId: { eq: $movieId }, role: { eq: "editor" } }) {
    user {
      id
      username
    }
  }
}

Yetkilendirme kontrollerinde @check ve @redact yönergeleri hakkında daha fazla bilgi edinmek için yetkilendirme verisi aramasıyla ilgili tartışmaya bakın.

Anahtarları doğrulamak için @check kullanma

_update gibi bazı değişiklik alanları, belirtilen anahtara sahip bir kayıt yoksa işlemsiz kalabilir. Benzer şekilde, aramalar boş değer veya boş liste döndürebilir. Bunlar hata olarak kabul edilmez ve bu nedenle geri alma işlemini tetiklemez.

Bu sonucu önlemek için @check yönergesi kullanılarak anahtarların bulunup bulunmadığını test edin.

# Delete by key, error if not found
mutation MustDeleteMovie($id: UUID!) @transaction {
  movie_delete(id: $id) @check(expr: "this != null", message: "Movie not found, therefore nothing is deleted")
}

Çok adımlı mutasyonları zincirlemek için response bağlamasını kullanma

İlgili kayıtlar oluşturmak için temel yaklaşım (ör. yeni bir Movie ve ilişkili bir MovieMetadata girişi) şu şekildedir:

  1. Movie için _insert mutasyonunu çağırma
  2. Oluşturulan filmin döndürülen anahtarını saklayın.
  3. Ardından, _insert kaydını oluşturmak için ikinci bir MovieMetadata mutasyonu çağırın.

Ancak SQL Connect ile bu yaygın durumu tek bir çok adımlı işlemde ele alabilirsiniz. Bunun için ikinci _insert'deki ilk _insert'ün sonuçlarına erişmeniz gerekir.

Başarılı bir film inceleme uygulaması oluşturmak çok fazla çalışma gerektirir. Yeni bir örnekle yapılacaklar listemizi takip edelim.

Alanları sunucu değerleriyle ayarlamak için response simgesini kullanın.

Aşağıdaki yapılacaklar listesi değişikliğinde:

  • response bağlaması, şu ana kadarki kısmi yanıt nesnesini temsil eder. Bu nesne, mevcut olanın öncesindeki tüm üst düzey değişiklik alanlarını içerir.
  • todoList_insert işleminin sonuçları, id (anahtar) alanını döndürür. Bu sonuçlara daha sonra response.todoList_insert.id içinde erişilir. Böylece yeni bir yapılacaklar öğesini hemen ekleyebiliriz.
mutation CreateTodoListWithFirstItem(
  $listName: String!,
  $itemContent: String!
) @transaction {
  # Sub-step 1:
  todoList_insert(data: {
    id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
    name: $listName,
  })
  # Sub-step 2:
  todo_insert(data: {
    listId_expr: "response.todoList_insert.id" # <-- Grab the newly generated ID from the partial response so far.
    content: $itemContent,
  })
}

response kullanarak @check ile alanları doğrulama

response, @check(expr: "...")'te de kullanılabilir. Bu sayede daha karmaşık sunucu tarafı mantığı oluşturmak için bu özelliği kullanabilirsiniz. Değişikliklerdeki query { … } adımlarıyla birlikte kullanıldığında, ek istemci-sunucu gidiş dönüşleri olmadan çok daha fazlasını elde edebilirsiniz.

Aşağıdaki örnekte, @check her zaman bağlı olduğu adımdan sonra çalıştığı için @check öğesinin response.query öğesine zaten erişimi olduğunu unutmayın.

mutation CreateTodoInNamedList(
  $listName: String!,
  $itemContent: String!
) @transaction {
  # Sub-step 1: Look up List.id by its name
  query
  @check(expr: "response.query.todoLists.size() > 0", message: "No such TodoList with the name!")
  @check(expr: "response.query.todoLists.size() < 2", message: "Ambiguous listName!") {
    todoLists(where: { name: $listName }) {
      id
    }
  }
  # Sub-step 2:
  todo_insert(data: {
    listId_expr: "response.todoLists[0].id" # <-- Now we have the parent list ID to insert to
    content: $itemContent,
  })
}

response bağlama hakkında daha fazla bilgi için CEL referansı bölümüne bakın.

@transaction ve query @check ile kesintiye uğrayan işlemleri anlama

Çok adımlı mutasyonlarda hatalarla karşılaşılabilir:

  • Veritabanı işlemleri başarısız olabilir.
  • sorgu @check mantığı işlemleri sonlandırabilir.

SQL Connect, çok adımlı mutasyonlarınızda @transaction yönergesini kullanmanızı önerir. Bu sayede daha tutarlı bir veritabanı ve istemci kodunda işlenmesi daha kolay olan mutasyon sonuçları elde edilir:

  • İlk hatada veya başarısız olan @check'da işlem sonlandırılır. Bu nedenle, sonraki alanların yürütülmesini veya CEL'in değerlendirilmesini yönetmeniz gerekmez.
  • Geri alma işlemleri, veritabanı hatalarına veya @check mantığına yanıt olarak gerçekleştirilir ve tutarlı bir veritabanı durumu elde edilir.
  • Geri alma hatası her zaman istemci koduna döndürülür.

@transaction kullanmamayı tercih edebileceğiniz bazı kullanım alanları olabilir. Örneğin, daha yüksek işleme hızı, ölçeklenebilirlik veya kullanılabilirlik istiyorsanız nihai tutarlılığı tercih edebilirsiniz. Ancak sonuçlara izin vermek için veritabanınızı ve istemci kodunuzu yönetmeniz gerekir:

  • Bir alan veritabanı işlemleri nedeniyle başarısız olursa sonraki alanlar yürütülmeye devam eder. Ancak başarısız olan @checklar yine de tüm işlemi sonlandırır.
  • Geri alma işlemleri gerçekleştirilmez. Bu nedenle, bazı güncellemelerin başarılı, bazılarının ise başarısız olduğu karma bir veritabanı durumu oluşur.
  • @check mantığınız önceki adımda okuma ve/veya yazma işlemlerinin sonuçlarını kullanıyorsa @check ile yaptığınız işlemler daha tutarsız sonuçlar verebilir.
  • İstemci koduna döndürülen sonuç, işlenecek daha karmaşık bir başarı ve başarısızlık yanıtı karışımı içerir.

SQL Connect mutasyonlarıyla ilgili yönergeler

Türleri ve tabloları tanımlarken kullandığınız yönergelere ek olarak, SQL Connect, işlemlerin davranışını artırmak için @auth, @check, @redact ve @transaction yönergelerini sağlar.

Yönerge Geçerli olduğu alanlar Açıklama
@auth Sorgular ve mutasyonlar Bir sorgu veya mutasyon için yetkilendirme politikasını tanımlar. Yetkilendirme ve onay kılavuzuna bakın.
@check Çok adımlı işlemlerdeki query alanlar Belirtilen alanların sorgu sonuçlarında mevcut olduğunu doğrular. Alan değerlerini test etmek için Common Expression Language (CEL) ifadesi kullanılır. Çok adımlı işlemler başlıklı makaleyi inceleyin.
@redact Sorgular İstemciden gelen yanıtın bir bölümünü çıkarır. Çok adımlı işlemler başlıklı makaleyi inceleyin.
@transaction Mutasyonlar Değişikliklerin her zaman bir veritabanı işleminde çalışmasını zorunlu kılar. Çok adımlı işlemler başlıklı makaleyi inceleyin.

Sonraki adımlar

İlginizi çekebilir: