Alt sorgularla birleştirme işlemleri gerçekleştirme

Arka plan

Pipeline işlemleri, Cloud Firestore için yeni bir sorgu arayüzüdür. Bu arayüz, karmaşık ifadeler içeren gelişmiş sorgu işlevselliği sağlar. Firestore Enterprise sürümü, ilişkili alt sorgular aracılığıyla ilişkisel tarzda birleştirmeleri destekler. Genellikle verilerin normalleştirilmemesini veya birden fazla istemci taraflı isteğin yapılmasını gerektiren birçok NoSQL veritabanının aksine, alt sorgular ilgili koleksiyonlardaki veya alt koleksiyonlardaki verileri doğrudan sunucuda birleştirmenize ve toplamanıza olanak tanır.

Alt sorgular, dış sorgu tarafından işlenen her belge için iç içe yerleştirilmiş bir ardışık düzeni yürüten ifadelerdir. Bu sayede, bir dokümanı ilgili alt koleksiyon öğeleriyle birlikte getirme veya mantıksal olarak bağlı verileri farklı kök koleksiyonlarda birleştirme gibi karmaşık veri alma kalıpları etkinleştirilir.

Kavramlar

Bu bölümde, alt sorguları kullanarak ardışık düzen işlemlerinde birleştirme gerçekleştirmenin temel kavramları tanıtılmaktadır.

İfade olarak alt sorgular

Alt sorgu, üst düzey bir aşama değildir. Bunun yerine, select(...), add_fields(...), where(...) veya sort(...) gibi ifadeleri kabul eden herhangi bir aşamada kullanılabilen bir ifadedir.

Cloud Firestore üç tür alt sorguyu destekler:

  • Dizi Alt Sorguları: Alt sorgunun tüm sonuç kümesini belge dizisi olarak gerçekleştirin.
  • Tek Değerli Alt Sorgular: Sayı, ortalama veya ilgili bir dokümandaki belirli bir alan gibi tek bir değerle değerlendirilir.
  • subcollection(...) Alt sorgular: Bire çok üst-alt ilişkisi için birleştirme işlemleri basitleştirildi.

Kapsam ve değişkenler

Birleştirme işlemi yazarken iç içe yerleştirilmiş alt sorgunun genellikle "dış" dokümandaki (üst) alanlara referans vermesi gerekir. Bu kapsamları birleştirmek için let(...) aşamasını (bazı SDK'larda define(...) olarak adlandırılır) kullanarak üst kapsamda değişkenler tanımlarsınız. Bu değişkenlere daha sonra variable(...) işlevi kullanılarak alt sorguda referans verilebilir.

Söz dizimi

Aşağıdaki bölümlerde, birleştirme işlemleri için söz dizimine genel bir bakış sunulmaktadır.

let(...) aşaması

let(...) aşaması (bazı SDK'larda define(...) olarak adlandırılır), üst kapsamdaki verileri açıkça getirip sonraki iç içe yerleştirilmiş kapsamlarda kullanılmak üzere adlandırılmış bir değişkene yerleştiren, filtreleme yapmayan bir aşamadır.

Web

    async function defineStageData() {
      await setDoc(doc(collection(db, "Authors"), "author_123"), {
        "id": "author_123",
        "name": "Jane Austen"
      });
    }
    
Swift
      func defineStageData() async throws {
      try await db.collection("authors").document("author_123").setData([
        "id": "author_123",
        "name": "Jane Austen"
      ])
    }
    

Kotlin

    fun defineStageData() {
        val author = hashMapOf(
            "id" to "author_123",
            "name" to "Jane Austen",
        )

        db.collection("Authors").document("author_123").set(author)
    }
  

Java

    public void defineStageData() {
        Map<String, Object> author = new HashMap<>();
        author.put("id", "author_123");
        author.put("name", "Jane Austen");

        db.collection("Authors").document("author_123").set(author);
    }
  

Dizi Alt Sorguları

Dizi alt sorgusu, alt sorgunun sonuç kümesinin tamamını bir dizide somutlaştıran özel bir ifade alt sorgusudur. Alt sorgu sıfır satır döndürürse boş bir dizi olarak değerlendirilir. Hiçbir zaman null dizisi döndürmez. Bu tür sorgular, iç içe yerleştirilmiş veya ilişkili bir koleksiyon oluşturma gibi durumlarda nihai sonuçta tüm sonuçların gerekli olduğu zamanlarda kullanışlıdır.

Sorgular, getirilmesi ve döndürülmesi gereken veri miktarını azaltmak için alt sorguda filtreleme, sıralama ve toplama işlemleri yaparak sorgunun maliyetini düşürmeye yardımcı olabilir. Alt sorgunun sırası dikkate alınır. Bu nedenle, alt sorgudaki sort(...) aşaması, nihai dizideki sonuçların sırasını kontrol eder.

Bir sorguyu diziye dönüştürmek için toArrayExpression() SDK sarmalayıcısını kullanın.

Web

    async function toArrayExpressionStageData() {
      await setDoc(doc(collection(db, "Projects"), "project_1"), {
        "id": "project_1",
        "name": "Alpha Build"
      });
      await addDoc(collection(db, "Tasks"), {
        "project_id": "project_1",
        "title": "System Architecture"
      });
      await addDoc(collection(db, "Tasks"), {
        "project_id": "project_1",
        "title": "Database Schema Design"
      });
    }
  

Yanıt

    {
        id: "project_1",
        name: "Alpha Build",
        taskTitles: [
          "System Architecture", "Database Schema Design"
      ]
    }
    
Swift
    async function toArrayExpressionStageData() {
      await setDoc(doc(collection(db, "Projects"), "project_1"), {
        "id": "project_1",
        "name": "Alpha Build"
      });
      await addDoc(collection(db, "Tasks"), {
        "project_id": "project_1",
        "title": "System Architecture"
      });
      await addDoc(collection(db, "Tasks"), {
        "project_id": "project_1",
        "title": "Database Schema Design"
      });
    }
    

Yanıt

    {
      id: "project_1",
      name: "Alpha Build",
      taskTitles: [
        "System Architecture", "Database Schema Design"
      ]
    }
    

Kotlin

    fun toArrayExpressionData() {
        val project = hashMapOf(
            "id" to "project_1",
            "name" to "Alpha Build",
        )
        db.collection("Projects").document("project_1").set(project)

        val task1 = hashMapOf(
            "project_id" to "project_1",
            "title" to "System Architecture",
        )
        db.collection("Tasks").add(task1)

        val task2 = hashMapOf(
            "project_id" to "project_1",
            "title" to "Database Schema Design",
        )
        db.collection("Tasks").add(task2)
    }
  

Yanıt

    {
      id: "project_1",
      name: "Alpha Build",
      taskTitles: [
        "System Architecture", "Database Schema Design"
      ]
    }
    

Java

      public void toArrayExpressionData() {
        Map<String, Object> project = new HashMap<>();
        project.put("id", "project_1");
        project.put("name", "Alpha Build");
        db.collection("Projects").document("project_1").set(project);

        Map<String, Object> task1 = new HashMap<>();
        task1.put("project_id", "project_1");
        task1.put("title", "System Architecture");
        db.collection("Tasks").add(task1);

        Map<String, Object> task2 = new HashMap<>();
        task2.put("project_id", "project_1");
        task2.put("title", "Database Schema Design");
        db.collection("Tasks").add(task2);
    }
  

Yanıt

    {
        id: "project_1",
        name: "Alpha Build",
        taskTitles: [
          "System Architecture", "Database Schema Design"
      ]
    }
    

Skaler Alt Sorgular

Skaler alt sorgular, genellikle select(...) veya where(...) aşamasında, tam sorguyu doğrudan oluşturmadan filtrelemeye izin vermek ya da alt sorgunun sonucunu elde etmek için kullanılır.

Sıfır sonuç üreten bir alt sorgu, null olarak değerlendirilirken birden fazla öğe olarak değerlendirilen bir alt sorgu, çalışma zamanı hatasıyla sonuçlanır.

Bir skaler alt sorgu sonuç başına yalnızca tek bir alan ürettiğinde alan, alt sorgunun üst düzey sonucu olacak şekilde yükseltilir. Bu durum en sık, alt sorgunun şeması tek bir alandan oluştuğu ve alt sorgunun select(field("user_name")) veya aggregate(countAll().as("total")) ile bittiği durumlarda görülür. Aksi takdirde, bir alt sorgu birden fazla alan üretebildiğinde bu alanlar bir haritaya sarılır.

Bir sorguyu skaler ifadeye dönüştürmek için toScalarExpression() SDK sarmalayıcısını kullanın.

Web

            async function toScalarExpressionStageData() {
              await setDoc(doc(collection(db, "Authors"), "author_202"), {
                "id": "author_202",
                "name": "Charles Dickens"
              });
              await addDoc(collection(db, "Books"), {
                "author_id": "author_202",
                "title": "Great Expectations",
                "rating": 4.8
              });
              await addDoc(collection(db, "Books"), {
                "author_id": "author_202",
                "title": "Oliver Twist",
                "rating": 4.5
              });
            }
        

Yanıt

        {
            "id": "author_202",
            "name": "Charles Dickens",
            "averageBookRating": 4.65
        }
      
Swift
        try await db.collection("authors").document("author_202").setData([
          "id": "author_202",
          "name": "Charles Dickens"
        ])
        try await db.collection("books").document().setData([
          "author_id": "author_202",
          "title": "Great Expectations",
          "rating": 4.8
        ])
        try await db.collection("books").document().setData([
          "author_id": "author_202",
          "title": "Oliver Twist",
          "rating": 4.5
        ])
        

Yanıt

        {
            "id": "author_202",
            "name": "Charles Dickens",
            "averageBookRating": 4.65
        }
      

Kotlin

        fun toScalarExpressionData() {
        val author = hashMapOf(
            "id" to "author_202",
            "name" to "Charles Dickens",
        )
        db.collection("Authors").document("author_202").set(author)

        val book1 = hashMapOf(
            "author_id" to "author_202",
            "title" to "Great Expectations",
            "rating" to 4.8,
        )
        db.collection("Books").add(book1)

        val book2 = hashMapOf(
            "author_id" to "author_202",
            "title" to "Oliver Twist",
            "rating" to 4.5,
        )
        db.collection("Books").add(book2)
    }
  

Yanıt

        {
            "id": "author_202",
            "name": "Charles Dickens",
            "averageBookRating": 4.65
        }
      

Java

       public void toScalarExpressionData() {
        Map<String, Object> author = new HashMap<>();
        author.put("id", "author_202");
        author.put("name", "Charles Dickens");
        db.collection("Authors").document("author_202").set(author);

        Map<String, Object> book1 = new HashMap<>();
        book1.put("author_id", "author_202");
        book1.put("title", "Great Expectations");
        book1.put("rating", 4.8);
        db.collection("Books").add(book1);

        Map<String, Object> book2 = new HashMap<>();
        book2.put("author_id", "author_202");
        book2.put("title", "Oliver Twist");
        book2.put("rating", 4.5);
        db.collection("Books").add(book2);
    }
  

Yanıt

        {
            "id": "author_202",
            "name": "Charles Dickens",
            "averageBookRating": 4.65
        }
      

subcollection(...) Alt sorgular

Aşama olarak sunulan subcollection(...) giriş aşaması, Cloud Firestore'nin hiyerarşik veri modeli üzerinde birleştirme işlemlerinin gerçekleştirilmesine olanak tanır. Hiyerarşik modelde sorguların, kendi alt koleksiyonlarındaki verilerle birlikte bir dokümanı alması gerekir. Bu işlemi, bir collection_group(...) giriş aşaması ve ardından üst referans üzerinde bir filtre kullanarak gerçekleştirebilirsiniz ancak subcollection(...) çok daha kısa bir söz dizimi sağlar.

Bu işlev, örtülü birleştirme koşulu dışında bir dizi alt sorgusuna benzer şekilde çalışır. İç içe yerleştirilmiş koleksiyon mevcut olmasa bile hiçbir doküman eşleşmezse boş bir sonuç döndürür.

Temelde söz dizimi kolaylığı sağlar: Hiyerarşik ilişkiyi çözmek için dış kapsamdaki dokümanın __name__ özelliğini otomatik olarak birleştirme anahtarı olarak kullanır. Bu nedenle, üst-alt ilişkisiyle bağlı koleksiyonlarda arama yapmak için tercih edilen yöntemdir.

En iyi uygulamalar

  • Belleği toArrayExpression() ile yönetme: Çok sayıda dokümanın oluşturulması sorgu belleği sınırını (128 MiB) aşabileceğinden toArrayExpression() alt sorgularını kullanırken dikkatli olun. Bunu azaltmak için alt sorguda select(...) kullanarak yalnızca gerekli alanları döndürün ve döndürülen belge sayısını sınırlamak için where(...) filtreleri uygulayın. Alt sorgu tarafından döndürülen belge sayısını sınırlamak için uygunsa limit(...) kullanabilirsiniz.
  • Dizine ekleme: Alt sorgunun where(...) ifadesinde kullanılan alanların dizine eklendiğinden emin olun. Yüksek performanslı birleştirmeler, tam tablo taramaları yerine dizin aramaları yapabilme özelliğine dayanır.

Sorgularla ilgili daha fazla en iyi uygulama için sorgu optimizasyonunu ele alan rehberimize göz atın.

Sınırlamalar

  • subcollection(...) kapsamı: subcollection(...) giriş aşaması yalnızca alt sorgularda desteklenir. Bunun nedeni, hiyerarşik ilişkiyi çözmek ve birleştirme işlemini gerçekleştirmek için üst dokümanın bağlamını gerektirmesidir.
  • İç İçe Yerleştirme Derinliği: Alt sorgular en fazla 20 kat iç içe yerleştirilebilir.
  • Bellek kullanımı: Gerçekleştirilmiş veriler için 128 MiB sınırı, birleştirilmiş tüm belgeler dahil olmak üzere sorgunun tamamı için geçerlidir.