Veritabanınızı Yapılandırın

Bu kılavuz, veri mimarisindeki bazı temel kavramları ve Firebase Gerçek Zamanlı Veritabanınızdaki JSON verilerini yapılandırmaya yönelik en iyi uygulamaları kapsar.

Düzgün yapılandırılmış bir veritabanı oluşturmak, biraz öngörü gerektirir. En önemlisi, bu süreci olabildiğince kolaylaştırmak için verilerin nasıl kaydedileceğini ve daha sonra alınacağını planlamanız gerekir.

Veriler nasıl yapılandırılır: bir JSON ağacıdır

Tüm Firebase Gerçek Zamanlı Veritabanı verileri JSON nesneleri olarak depolanır. Veritabanını bulutta barındırılan bir JSON ağacı olarak düşünebilirsiniz. SQL veritabanının aksine tablo veya kayıt yoktur. JSON ağacına veri eklediğinizde, mevcut JSON yapısında ilişkili bir anahtara sahip bir düğüm haline gelir. Kullanıcı kimlikleri veya anlamsal adlar gibi kendi anahtarlarınızı sağlayabilirsiniz veya bunlar childByAutoId kullanılarak sizin için sağlanabilir.

Kendi anahtarlarınızı oluşturursanız, bunların UTF-8 kodlu olması gerekir, maksimum 768 bayt olabilir ve . , $ , # , [ , ] , / veya ASCII kontrol karakterleri 0-31 veya 127. Değerlerin kendisinde de ASCII kontrol karakterlerini kullanamazsınız.

Örneğin, kullanıcıların temel bir profili ve kişi listesini saklamasına olanak tanıyan bir sohbet uygulamasını düşünün. Tipik bir kullanıcı profili, /users/$uid gibi bir yolda bulunur. alovelace kullanıcısının şuna benzer bir veritabanı girişi olabilir:

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}

Veritabanı bir JSON ağacı kullansa da, veritabanında depolanan veriler, daha bakımı kolay kod yazmanıza yardımcı olmak için mevcut JSON türlerine karşılık gelen belirli yerel türler olarak temsil edilebilir.

Veri yapısına yönelik en iyi uygulamalar

Verilerin iç içe yerleştirilmesinden kaçının

Firebase Gerçek Zamanlı Veritabanı, verilerin 32 seviyeye kadar derinliğe yerleştirilmesine izin verdiğinden, bunun varsayılan yapı olması gerektiğini düşünebilirsiniz. Ancak veritabanınızdaki bir konuma veri getirdiğinizde, aynı zamanda onun tüm alt düğümlerini de alırsınız. Ayrıca birine veritabanınızdaki bir düğümde okuma veya yazma erişimi verdiğinizde, o düğümün altındaki tüm verilere de erişim izni vermiş olursunuz. Bu nedenle pratikte veri yapınızı mümkün olduğunca düz tutmak en iyisidir.

İç içe geçmiş verilerin neden kötü olduğuna dair bir örnek için aşağıdaki çoklu iç içe yapıyı göz önünde bulundurun:

{
  // This is a poorly nested data architecture, because iterating the children
  // of the "chats" node to get a list of conversation titles requires
  // potentially downloading hundreds of megabytes of messages
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "messages": {
        "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
        "m2": { ... },
        // a very long list of messages
      }
    },
    "two": { ... }
  }
}

Bu iç içe geçmiş tasarımla veriler arasında yineleme yapmak sorunlu hale gelir. Örneğin, sohbet konuşmalarının başlıklarının listelenmesi, tüm üyeler ve mesajlar dahil olmak üzere chats ağacının tamamının istemciye indirilmesini gerektirir.

Veri yapılarını düzleştirin

Veriler bunun yerine denormalizasyon olarak da adlandırılan ayrı yollara bölünürse, gerektiğinde ayrı çağrılarda verimli bir şekilde indirilebilir. Bu düzleştirilmiş yapıyı düşünün:

{
  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },

  // Messages are separate from data we may want to iterate quickly
  // but still easily paginated and queried, and organized by chat
  // conversation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  }
}

Artık konuşma başına yalnızca birkaç bayt indirerek, odaların bir kullanıcı arayüzünde listelenmesi veya görüntülenmesi için meta verileri hızlı bir şekilde getirerek oda listesinde yineleme yapmak mümkün. Mesajlar ayrı ayrı alınıp geldikçe görüntülenebilir, böylece kullanıcı arayüzünün duyarlı ve hızlı kalması sağlanır.

Ölçeklenen veriler oluşturun

Uygulama oluştururken listenin bir alt kümesini indirmek genellikle daha iyidir. Liste binlerce kayıt içeriyorsa bu durum özellikle yaygındır. Bu ilişki statik ve tek yönlü olduğunda, alt nesneleri basitçe üst öğenin altına yerleştirebilirsiniz.

Bazen bu ilişki daha dinamik olabilir veya bu verinin normalleştirilmesi gerekebilir. Çoğu zaman , Verileri Alma bölümünde tartışıldığı gibi, verilerin bir alt kümesini almak için bir sorgu kullanarak verileri denormalize edebilirsiniz.

Ancak bu bile yetersiz kalabilir. Örneğin kullanıcılar ve gruplar arasındaki iki yönlü ilişkiyi düşünün. Kullanıcılar bir gruba ait olabilir ve gruplar bir kullanıcı listesinden oluşur. Sıra bir kullanıcının hangi gruplara ait olduğuna karar vermeye geldiğinde işler karmaşıklaşıyor.

İhtiyaç duyulan şey, bir kullanıcının ait olduğu grupları listelemenin ve yalnızca bu gruplara ilişkin verileri getirmenin zarif bir yoludur. Grupların bir dizini burada çok yardımcı olabilir:

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

Bunun, ilişkiyi hem Ada'nın kaydında hem de grup altında saklayarak bazı verileri kopyaladığını fark edebilirsiniz. Artık alovelace bir grup altında indekslendi ve techpioneers Ada'nın profilinde listelendi. Yani Ada'yı gruptan silmek için iki yerden güncellenmesi gerekiyor.

Bu, iki yönlü ilişkiler için gerekli bir fazlalıktır. Kullanıcı veya grup listesi milyonlara vardığında veya Gerçek Zamanlı Veritabanı güvenlik kuralları bazı kayıtlara erişimi engellediğinde bile Ada'nın üyeliklerini hızlı ve etkili bir şekilde almanıza olanak tanır.

Kimlikleri anahtar olarak listeleyerek ve değeri true olarak ayarlayarak verileri tersine çeviren bu yaklaşım, bir anahtarın kontrolünü /users/$uid/groups/$group_id okumak ve bunun null olup olmadığını kontrol etmek kadar basit hale getirir. Dizin, verileri sorgulamaktan veya taramaktan çok daha hızlı ve çok daha verimlidir.

Sonraki adımlar