Veritabanınızı Yapılandırma

Bu kılavuzda, veri mimarisindeki bazı temel kavramlar ve Firebase Realtime Database'nızdaki JSON verilerini yapılandırmaya yönelik en iyi uygulamalar ele alınmaktadır.

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

Veriler nasıl yapılandırılır? JSON ağacıdır.

Tüm Firebase Realtime Database 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, tablolar veya kayıtlar yoktur. JSON ağacına veri eklediğinizde, bu veri mevcut JSON yapısında ilişkili bir anahtara sahip bir düğüm haline gelir. Kullanıcı kimlikleri veya anlamlı adlar gibi kendi anahtarlarınızı sağlayabilir ya da anahtarlar push() yöntemi kullanılarak sizin için sağlanabilir.

Kendi anahtarlarınızı oluşturursanız bunlar UTF-8 kodlamalı olmalı, en fazla 768 bayt olabilir ve ., $, #, [, ], / veya ASCII kontrol karakterleri 0-31 ya da 127'yi içeremez. Değerlerin kendisinde de ASCII kontrol karakterleri kullanamazsınız.

Örneğin, kullanıcıların temel bir profil ve kişi listesi depolamasına olanak tanıyan bir sohbet uygulamasını ele alalım. Tipik bir kullanıcı profili, /users/$uid gibi bir yolda bulunur. Kullanıcı alovelace'nın veritabanı girişi şu şekilde olabilir:

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

Veritabanı bir JSON ağacı kullanmasına rağmen, daha sürdürülebilir kod yazmanıza yardımcı olmak için veritabanında depolanan veriler, kullanılabilir JSON türlerine karşılık gelen belirli yerel türler olarak gösterilebilir.

Veri yapısıyla ilgili en iyi uygulamalar

Verileri iç içe yerleştirmeyin

Firebase Realtime Database, verilerin 32 seviyeye kadar iç içe yerleştirilmesine izin verdiğinden bunun varsayılan yapı olması gerektiğini düşünebilirsiniz. Ancak veritabanınızdaki bir konumda veri getirdiğinizde tüm alt düğümleri de alırsınız. Ayrıca, veritabanınızdaki bir düğümde bir kullanıcıya okuma veya yazma erişimi verdiğinizde, bu düğümün altındaki tüm verilere de erişim izni vermiş olursunuz. Bu nedenle, uygulamada veri yapınızı mümkün olduğunca düz tutmanız en iyisidir.

İç içe yerleştirilmiş verilerin neden kötü olduğuna dair bir örnek olarak aşağıdaki iç içe yerleştirilmiş yapıyı inceleyin:

{
  // 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 yerleştirilmiş tasarımda veriler arasında yineleme yapmak sorunlu hale gelir. Örneğin, sohbet görüşmelerinin başlıklarını listelemek için tüm üyeler ve iletiler dahil olmak üzere chats ağacın tamamının istemciye indirilmesi gerekir.

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

Veriler bunun yerine ayrı yollara bölünürse (denormalizasyon olarak da adlandırılır) gerektiğinde ayrı çağrılarla verimli bir şekilde indirilebilir. Şu düzleştirilmiş yapıyı göz önünde bulundurun:

{
  // 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 görüşme başına yalnızca birkaç bayt indirerek oda listesinde yineleme yapabilir, listeleme veya odaları kullanıcı arayüzünde gösterme için meta verileri hızlıca getirebilirsiniz. İletiler ayrı ayrı alınabilir ve geldikçe gösterilebilir. Böylece kullanıcı arayüzü hızlı ve yanıt vermeye devam edebilir.

Ölçeklenebilir veriler oluşturma

Uygulama geliştirirken genellikle listenin bir alt kümesini indirmek daha iyidir. Bu durum, özellikle listede binlerce kayıt varsa yaygındır. Bu ilişki statik ve tek yönlü olduğunda alt nesneleri üst öğenin altına yerleştirmeniz yeterlidir.

Bazen bu ilişki daha dinamik olabilir veya bu verilerin normalleştirilmemesi gerekebilir. Çoğu zaman, Verileri Alma bölümünde açıklandığı gibi, verilerin bir alt kümesini almak için sorgu kullanarak verileri normalleştirme işlemini geri alabilirsiniz.

Ancak bu bile yetersiz olabilir. Örneğin, kullanıcılar ve gruplar arasındaki iki yönlü ilişkiyi ele alalım. Kullanıcılar bir gruba ait olabilir ve gruplar bir kullanıcı listesinden oluşur. Kullanıcının hangi gruplara ait olduğuna karar verme zamanı geldiğinde işler karışır.

Kullanıcının ait olduğu grupları listelemek ve yalnızca bu gruplara ait verileri getirmek için zarif bir yöntem gerekir. Grupların dizini bu konuda büyük ölçüde 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
      }
    },
    // ...
  }
}

Bu işlem, ilişkiyi hem Ada'nın kaydında hem de grubun altında saklayarak bazı verileri kopyalayabilir. Artık alovelace bir grup altında dizine ekleniyor ve techpioneers, Ada'nın profilinde listeleniyor. Bu nedenle, Ada'yı gruptan silmek için iki yerde güncelleme yapılması gerekir.

Bu, iki yönlü ilişkiler için gerekli bir yedekliliktir. Kullanıcı veya grup listesi milyonlara ulaşsa ya da Realtime Database güvenlik kuralları bazı kayıtlara erişimi engellese bile Ada'nın üyeliklerini hızlı ve verimli bir şekilde almanıza olanak tanır.

Bu yaklaşımda, kimlikler anahtar olarak listelenerek ve değer doğru olarak ayarlanarak veriler tersine çevrilir. Böylece, bir anahtarın kontrol edilmesi /users/$uid/groups/$group_id okunup null olup olmadığına bakmak kadar kolay olur. Dizine ekleme, verileri sorgulamaktan veya taramaktan daha hızlı ve çok daha verimlidir.

Sonraki adımlar