Google si impegna a promuovere l'equità razziale per le comunità nere. Vedi come.
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Struttura il tuo database

Prima di iniziare

Prima di poter utilizzare il database in tempo reale , è necessario:

  • Registra il tuo progetto Unity e configuralo per usare Firebase.

    • Se il tuo progetto Unity utilizza già Firebase, è già registrato e configurato per Firebase.

    • Se non si dispone di un progetto Unity, è possibile scaricare un'app di esempio .

  • Aggiungi l' SDK di Firebase Unity (in particolare, FirebaseDatabase.unitypackage ) al tuo progetto Unity.

Si noti che l'aggiunta di Firebase al progetto Unity implica attività sia nella console Firebase che nel progetto Unity aperto (ad esempio, scaricare i file di configurazione di Firebase dalla console, quindi spostarli nel progetto Unity).

Strutturare i dati

Questa guida copre alcuni dei concetti chiave dell'architettura dei dati e le migliori pratiche per strutturare i dati JSON nel database in tempo reale di Firebase.

Costruire un database adeguatamente strutturato richiede un bel po 'di riflessione. Ancora più importante, è necessario pianificare il modo in cui i dati verranno salvati e successivamente recuperati per rendere il processo il più semplice possibile.

Come sono strutturati i dati: è un albero JSON

Tutti i dati del database in tempo reale di Firebase sono archiviati come oggetti JSON. Puoi pensare al database come un albero JSON ospitato su cloud. A differenza di un database SQL, non ci sono tabelle o record. Quando si aggiungono dati all'albero JSON, questo diventa un nodo nella struttura JSON esistente con una chiave associata. È possibile fornire le proprie chiavi, come ID utente o nomi semantici, oppure possono essere fornite utilizzando il metodo Push() .

Se si creano le proprie chiavi, devono essere codificate UTF-8, possono avere un massimo di 768 byte e non possono contenere . , $ , # , [ , ] , / o caratteri di controllo ASCII 0-31 o 127. Non è possibile utilizzare nemmeno i caratteri di controllo ASCII nei valori stessi.

Ad esempio, considera un'applicazione di chat che consente agli utenti di memorizzare un profilo di base e un elenco di contatti. Un tipico profilo utente si trova in un percorso, come /users/$uid . L'utente alovelace potrebbe avere una voce di database simile a questa:

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

Sebbene il database utilizzi un albero JSON, i dati memorizzati nel database possono essere rappresentati come determinati tipi nativi che corrispondono ai tipi JSON disponibili per aiutarti a scrivere codice più gestibile.

Best practice per la struttura dei dati

Evitare di annidare i dati

Poiché il database in tempo reale di Firebase consente di annidare i dati fino a 32 livelli di profondità, potresti essere tentato di pensare che questa dovrebbe essere la struttura predefinita. Tuttavia, quando si recuperano dati in una posizione nel database, si recuperano anche tutti i suoi nodi figlio. Inoltre, quando si concede a qualcuno l'accesso in lettura o scrittura a un nodo nel database, si concede anche l'accesso a tutti i dati in quel nodo. Pertanto, in pratica, è meglio mantenere la struttura dei dati il ​​più piatta possibile.

Per un esempio del motivo per cui i dati nidificati sono errati, prendere in considerazione la seguente struttura a nidificazione multipla:

{
  // 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": { ... }
  }
}

Con questo design nidificato, l'iterazione dei dati diventa problematica. Ad esempio, per elencare i titoli delle conversazioni in chat è necessario scaricare sul client l'intero albero delle chats , inclusi tutti i membri e i messaggi.

Appiattire le strutture dati

Se i dati vengono invece suddivisi in percorsi separati, detti anche denormalizzazione, possono essere scaricati in modo efficiente in chiamate separate, se necessario. Considera questa struttura appiattita:

{
  // 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": { ... }
  }
}

Ora è possibile scorrere l'elenco delle sale scaricando solo pochi byte per conversazione, recuperando rapidamente i metadati per elencare o visualizzare le sale in un'interfaccia utente. I messaggi possono essere recuperati separatamente e visualizzati al loro arrivo, consentendo all'interfaccia utente di rimanere reattiva e veloce.

Crea dati scalabili

Quando si creano app, è spesso meglio scaricare un sottoinsieme di un elenco. Ciò è particolarmente comune se l'elenco contiene migliaia di record. Quando questa relazione è statica e unidirezionale, puoi semplicemente nidificare gli oggetti figlio sotto il genitore.

A volte, questa relazione è più dinamica o potrebbe essere necessario denormalizzare questi dati. Molte volte è possibile denormalizzare i dati utilizzando una query per recuperare un sottoinsieme dei dati, come discusso in Recupera dati .

Ma anche questo potrebbe essere insufficiente. Si consideri, ad esempio, una relazione bidirezionale tra utenti e gruppi. Gli utenti possono appartenere a un gruppo e i gruppi comprendono un elenco di utenti. Quando arriva il momento di decidere a quali gruppi appartiene un utente, le cose si complicano.

Ciò che serve è un modo elegante per elencare i gruppi a cui appartiene un utente e recuperare solo i dati per quei gruppi. Un indice di gruppi può essere di grande aiuto qui:

// 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
      }
    },
    ...
  }
}

Potresti notare che questo duplica alcuni dati memorizzando la relazione sia nel registro di Ada che nel gruppo. Ora alovelace è indicizzato in un gruppo e techpioneers è elencato nel profilo di Ada. Quindi, per eliminare Ada dal gruppo, deve essere aggiornato in due punti.

Questa è una ridondanza necessaria per le relazioni a due vie. Ti consente di recuperare le iscrizioni Ada in modo rapido ed efficiente, anche quando l'elenco di utenti o gruppi si riduce a milioni o quando le regole di sicurezza del database in tempo reale impediscono l'accesso ad alcuni dei record.

Questo approccio, invertendo i dati elencando gli ID come chiavi e impostando il valore su true, rende il controllo di una chiave semplice come leggere /users/$uid/groups/$group_id e verificare se è null . L'indice è più veloce e molto più efficiente rispetto all'interrogazione o alla scansione dei dati.

Prossimi passi