Data Connect mutasyonlarını uygulama

Firebase Data Connect, Google 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 sorgular 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. Data 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ı ortamlardan çalıştırılır. Bu komutları Firebase konsolunda, Firebase Admin SDK kullanılarak ayrıcalıklı ortamlarda ve Data Connect VS Code uzantımız kullanılarak yerel geliştirme ortamlarında oluşturup yürütebilirsiniz.

Bu kılavuzda dağıtılabilir mutasyonlar daha ayrıntılı olarak ele alınmaktadır.

Data Connect mutasyonlarının özellikleri

Data 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 Data Connect'ın GraphQL'e yönelik uzantılarıyla daha hızlı ve verimli uygulamalar için gelişmiş mutasyonlar uygulayabilirsiniz:

  • Kayıtlarda 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 kullanma
  • Verileri aramak için çok adımlı mutasyon işlemleri sırasında sorgular gerçekleştirerek kod satırlarını ve sunucuya gidiş dönüşleri kaydedin.

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

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

Oluşturulan alanları, tek tablolarda tek tek kayıt 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. Data 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($data: Movie_Data!) {
  movie_insert(data: $data) { key }
}


movie_update alanı ile mutasyon

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!, $data: Movie_Data!) {
  movie_update(key: $myKey, data: $data) { key }
}


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ıyla silmek için bu alanı kullanın.

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

Mutasyonun temel unsurları

Data Connect mutasyonları, Data Connect uzantıları olan GraphQL mutasyonlarıdır. Normal bir GraphQL mutasyonunda olduğu gibi, bir işlem adı ve GraphQL değişkenlerinin listesini tanımlayabilirsiniz.

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

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

  • mutation türü tanımı
  • 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üncellemeleri gerçekleştirme

Güncellemeler Yapımcılar ve yönetmenler, bu ortalama puanların trend 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
    }
  })
}

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

  • inc: Int, Int64, Float, Date ve Timestamp veri türlerini artırmak için
  • 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 halihazırda mevcut değilse add simgesini tıklayarak öğeleri liste türlerine(Vektör listeleri hariç) ekleyin.
  • Vektör listeleri hariç tüm liste türlerindeki öğeleri kaldırmak için remove
  • append(Vektör listeleri hariç) öğeleri liste türlerine eklemek için
  • prepend, vektör listeleri hariç liste türlerine öğe 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

Data 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 Data Connect otomatik olarak oluşturulan kısa nesne tanımlayıcılarıdır. Temel ölçekler, verilerinizin kimliği ve yapısı hakkındaki bilgileri tek bir çağrıda bulmanıza olanak tanıyarak verimlilikle ilgilidir. Yeni kayıtlarda sıralı işlemler yapmak istediğinizde ve yaklaşan işlemlere aktarmak için benzersiz bir tanımlayıcıya ihtiyacınız olduğunda, ayrıca daha karmaşık ek işlemler yapmak için ilişkisel anahtarlara erişmek istediğinizde özellikle yararlı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 kullanılarak alana erişildiğinde zaman damgası uygulanan bir alan tanımlayabilirsiniz updatedAt: Timestamp! @default(expr: "request.time").

Gelişmiş değişiklikler yazma: Data 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 Data 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 değerini 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 skalar referansındaki _Expr skalarlarına bakın.

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

Tek bir mutasyona 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şlemleri ve dolayısıyla maliyetlerden tasarruf sağlar.

Data Connect, aşağıdakileri destekleyerek mutasyonlarınızda çok adımlı mantık uygulamanıza olanak tanır:

  • Birden fazla yazma alanı

  • Mutasyonlarınızda birden fazla okuma alanı (query alan anahtar kelimesi kullanılarak).

  • İlişkisel veritabanlarından bilinen 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:

    • Değişiklik 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önergesinde, expr: bağımsız değişkeni aracılığıyla
    • Sunucu değerleriyle, field_expr söz dizimini kullanarak

@transaction yönergesi

Çok adımlı değişiklikler için destek, işlemler kullanılarak 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 olmadan yapılan 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 ile yapılan mutasyonların tamamen başarılı veya tamamen başarısız olması 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.

Örnek olarak, aşağıdaki sorgu alanı, bir isteği gönderenin bir filmi düzenleyebilecek kullanıcıları görüntülemek için uygun bir "yönetici" rolüne sahip olup olmadığını kontrol eder.

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 kontrollerindeki @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ı mutasyon alanları, belirtilen anahtara sahip bir kayıt yoksa işlem yapmayabilir. 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 (örneğin, 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, MovieMetadata kaydını oluşturmak için ikinci bir _insert mutasyonunu çağırın.

Ancak Data 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 yorumu uygulaması oluşturmak çok fazla çalışma gerektirir. Yeni bir örnekle yapılacaklar listemizi takip edelim.

Alanları sunucu değerleriyle ayarlamak için response kullanma

Aşağıdaki yapılacaklar listesi mutasyonunda:

  • response bağlaması, şu ana kadarki kısmi yanıt nesnesini temsil eder. Bu nesne, mevcut olanın öncesindeki tüm üst düzey mutasyon 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 alanları @check ile doğrulayın.

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.

Data 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 hata veya başarısız @check işleminde 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 @check'ler yine de tüm işlemi sonlandırır.
  • Geri alma işlemleri yapılmaz. 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.

Data Connect mutasyonlarıyla ilgili yönergeler

Türleri ve tabloları tanımlarken kullandığınız yönergelere ek olarak, Data 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ıttaki bir bölümü çıkarır. Çok adımlı işlemler başlıklı makaleyi inceleyin.
@transaction Değişiklikler 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: