Obtén una FIRDatabaseReference
Para leer o escribir en la base de datos, necesitas una instancia de FIRDatabaseReference
:
Swift
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
Lectura y escritura de listas
Agrega datos a una lista de datos
Usa el método childByAutoId
para agregar datos a una lista en aplicaciones multiusuario. Cada vez que se agrega un elemento secundario nuevo a la referencia de Firebase especificada, el método childByAutoId
genera una clave única. Cuando se usan estas claves generadas de forma automática para cada elemento nuevo de la lista, varios clientes pueden agregar elementos secundarios a la misma ubicación, al mismo tiempo y sin conflictos de escritura. La clave única que genera childByAutoId
se basa en una marca de tiempo. Por lo tanto, los elementos de las listas se ordenan cronológicamente de forma automática.
Puedes usar la referencia a los datos nuevos que muestra el método childByAutoId
para obtener el valor de la clave generada automáticamente del elemento secundario o configurar los datos de dicho elemento.
Si se llama a getKey
en una referencia childByAutoId
, se muestra la clave generada de forma automática.
Puedes usar estas claves generadas de manera automática para simplificar la compactación de tu estructura de datos. Para obtener más información, consulta el ejemplo de fan-out de datos.
Detecta eventos secundarios
Los eventos secundarios se activan en respuesta a operaciones específicas que se ejecutan en los
elementos secundarios de un nodo a partir de una operación, como un elemento secundario nuevo que se agrega a través del método
childByAutoId
o un elemento secundario que se actualiza a través del método
updateChildValues
.
Tipo de evento | Uso común |
---|---|
FIRDataEventTypeChildAdded |
Recupera listas de elementos o detecta elementos agregados a una lista. Este evento se activa una vez por cada elemento secundario existente y otra vez cuando se agrega un elemento secundario nuevo a la ruta de acceso especificada. El agente de escucha recibe una instantánea que contiene los datos del nuevo elemento secundario. |
FIRDataEventTypeChildChanged |
Detecta cambios en los elementos de una lista. Este evento se activa cuando se modifica un nodo secundario. Esto incluye cualquier modificación en los descendientes del nodo secundario. La instantánea que se pasa al agente de escucha de eventos contiene los datos actualizados del elemento secundario. |
FIRDataEventTypeChildRemoved |
Detecta cuando se quitan elementos de una lista. Este evento se activa cuando se quita un elemento secundario inmediato. El resumen que se pasa al bloque de devolución de llamada contiene los datos del elemento secundario que se quitó. |
FIRDataEventTypeChildMoved |
Detecta cambios en el orden de los elementos de una lista ordenada.
Este evento se activa cada vez que una actualización hace que se cambie el orden del elemento secundario. Se usa con datos que se ordenan con queryOrderedByChild
o queryOrderedByValue .
|
Cada uno de estos, en combinación, puede ser útil para detectar cambios en un nodo específico de una base de datos. Por ejemplo, una app social de blogs podría usar estos métodos en combinación para supervisar la actividad en los comentarios de una publicación, como se muestra a continuación:
Swift
// Listen for new comments in the Firebase database commentsRef.observe(.childAdded, with: { (snapshot) -> Void in self.comments.append(snapshot) self.tableView.insertRows( at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) }) // Listen for deleted comments in the Firebase database commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in let index = self.indexOfMessage(snapshot) self.comments.remove(at: index) self.tableView.deleteRows( at: [IndexPath(row: index, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) })
Objective-C
// Listen for new comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) { [self.comments addObject:snapshot]; [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments] ] withRowAnimation:UITableViewRowAnimationAutomatic]; }]; // Listen for deleted comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildRemoved withBlock:^(FIRDataSnapshot *snapshot) { int index = [self indexOfMessage:snapshot]; [self.comments removeObjectAtIndex:index]; [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]] withRowAnimation:UITableViewRowAnimationAutomatic]; }];
Detecta eventos de valores
Si bien escuchar para detectar eventos secundarios es la manera recomendada de leer listas de datos, existen situaciones en las que escuchar para detectar eventos de valores en una referencia de lista puede ser útil.
Si agregas un observador de FIRDataEventTypeValue
value a una lista de datos, el resultado será una lista completa de los datos en forma de una sola DataSnapshot. Si le aplicas un bucle a ese resultado, puedes acceder a cada elemento secundario.
Incluso cuando hay una sola coincidencia para la consulta, la instantánea es una lista, aunque contenga un solo elemento. Para acceder al elemento, debes aplicar un bucle al resultado:
Swift
_commentsRef.observe(.value) { snapshot in for child in snapshot.children { ... } }
Objective-C
[_commentsRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // Loop over children NSEnumerator *children = [snapshot children]; FIRDataSnapshot *child; while (child = [children nextObject]) { // ... } }];
Este patrón puede ser útil cuando quieres recuperar todos los elementos secundarios de una lista en una sola operación, en lugar de escuchar para detectar cada evento secundario que se agrega.
Cómo ordenar y filtrar datos
Puedes usar la clase FIRDatabaseQuery
de Realtime Database para recuperar datos ordenados
por clave, por valor o por valor del elemento secundario. También puedes filtrar el resultado ordenado de acuerdo con una cantidad específica de resultados o un rango de claves o valores.
Ordena los datos
Para recuperar datos ordenados, comienza por especificar uno de los métodos de ordenamiento, a fin de determinar cómo se presentarán los resultados:
Método | Uso |
---|---|
queryOrderedByKey
| Ordena los resultados según las claves secundarias. |
queryOrderedByValue |
Ordena los resultados según los valores secundarios. |
queryOrderedByChild |
Ordena los resultados según el valor de una clave secundaria especificada o una ruta de acceso secundaria anidada. |
Puedes usar solo un método de ordenamiento a la vez. Si llamas a un método de ordenamiento varias veces en la misma consulta, se genera un error.
El siguiente ejemplo demuestra cómo podrías recuperar una lista de las principales publicaciones de un usuario según la cantidad de estrellas que tienen:
Swift
// My top posts by number of stars let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
Objective-C
// My top posts by number of stars FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"] child:[super getUid]] queryOrderedByChild:@"starCount"];
Esta consulta recupera las publicaciones del usuario desde la ruta de acceso de la base de datos según su ID de usuario, ordenadas de acuerdo con la cantidad de estrellas que recibió cada publicación. Esta técnica de usar ID como claves de índice se denomina “fan-out de datos”. Puedes obtener más información al respecto en Estructura tu base de datos.
La llamada al método queryOrderedByChild
especifica la clave secundaria según la que se deben ordenar los resultados. En este ejemplo, las publicaciones se ordenan según el valor del elemento secundario "starCount"
en cada una de ellas. Las consultas también se pueden ordenar por campos secundarios anidados si tienes datos con la estructura siguiente:
"posts": { "ts-functions": { "metrics": { "views" : 1200000, "likes" : 251000, "shares": 1200, }, "title" : "Why you should use TypeScript for writing Cloud Functions", "author": "Doug", }, "android-arch-3": { "metrics": { "views" : 900000, "likes" : 117000, "shares": 144, }, "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)", "author": "Doug", } },
En este caso, podemos ordenar nuestros elementos de lista por valores anidados en la clave metrics
si especificamos la ruta de acceso relativa al elemento secundario anidado en nuestra llamada queryOrderedByChild
.
Swift
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")
Objective-C
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];
Para obtener más información sobre cómo se ordenan otros tipos de datos, consulta la sección Cómo se ordenan los datos de las consultas.
Cómo filtrar datos
Para filtrar datos, puedes combinar cualquiera de los métodos de límite o rango con un método de ordenamiento cuando generes una consulta.
Método | Uso |
---|---|
queryLimitedToFirst |
Configura la cantidad máxima de elementos que pueden mostrarse desde el comienzo de la lista de resultados ordenada. |
queryLimitedToLast |
Configura la cantidad máxima de elementos que pueden mostrarse desde el final de la lista de resultados ordenada. |
queryStartingAtValue |
Muestra elementos con un valor igual o superior a la clave o el valor que se especificó según el método de ordenamiento seleccionado. |
queryStartingAfterValue |
Muestra elementos con un valor superior a la clave o el valor que se especificó según el método de ordenamiento seleccionado. |
queryEndingAtValue |
Muestra elementos con un valor inferior o igual a la clave o el valor que se especificó según el método de ordenamiento seleccionado. |
queryEndingBeforeValue |
Muestra elementos con un valor inferior a la clave o el valor especificados, según el método de ordenamiento seleccionado. |
queryEqualToValue |
Muestra elementos con un valor igual a la clave o el valor que se especificó según el método de ordenamiento seleccionado. |
A diferencia de los métodos de ordenamiento, las funciones de límite o rango pueden combinarse.
Por ejemplo, puedes combinar los métodos queryStartingAtValue
y queryEndingAtValue
para limitar los resultados a un rango de valores específico.
Limita la cantidad de resultados
Puedes usar los métodos queryLimitedToFirst
y queryLimitedToLast
a fin de establecer una cantidad máxima de elementos secundarios que se sincronicen para una devolución de llamada determinada. Por ejemplo, si
usas queryLimitedToFirst
para establecer un límite de 100, inicialmente solo recibes hasta
100 devoluciones de llamada de tipo FIRDataEventTypeChildAdded
. Si hay menos de 100 elementos almacenados en la base de datos de Firebase, se activa una devolución de llamada FIRDataEventTypeChildAdded
por cada elemento.
A medida que los elementos cambien, recibirás devoluciones de llamadas de tipo FIRDataEventTypeChildAdded
por los elementos que ingresen en la consulta y devoluciones de llamadas de tipo FIRDataEventTypeChildRemoved
por los elementos que queden fuera para que el número total continúe siendo 100.
El siguiente ejemplo demuestra cómo la app de blog del ejemplo puede recuperar una lista de las 100 publicaciones más recientes de todos los usuarios:
Swift
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!
Objective-C
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];
Filtra por clave o valor
Puedes usar queryStartingAtValue
, queryStartingAfterValue
, queryEndingAtValue
, queryEndingBeforeValue
y queryEqualToValue
a fin de elegir puntos de inicio, finalización y equivalencia arbitrarios para las consultas. Esto puede ser útil para paginar datos o detectar elementos con campos secundarios que tengan un valor específico.
Cómo se ordenan los datos de las consultas
En esta sección, se explica cómo se ordenan los datos en cada uno de los métodos de ordenamiento de la clase FIRDatabaseQuery
.
queryOrderedByKey
Cuando ordenas los datos con queryOrderedByKey
, los datos se muestran en orden ascendente, según la clave.
- Los elementos secundarios con una clave que puede analizarse como un número entero de 32 bits van primero, ordenados en sentido ascendente.
- Los elementos secundarios con un valor de string como clave van después y ordenados de manera lexicográfica, en sentido ascendente.
queryOrderedByValue
Cuando usas queryOrderedByValue
, los elementos secundarios se ordenan según el valor. Se utilizan los mismos criterios de orden que para queryOrderedByChild
, excepto que se usa el valor del nodo en lugar del valor de una clave secundaria especificada.
queryOrderedByChild
Cuando usas queryOrderedByChild
, los datos que contienen la clave secundaria especificada se ordenan de la siguiente manera:
- Los elementos secundarios cuyas claves secundarias especificadas posean el valor
nil
irán en primer lugar. - A continuación, aparecerán los elementos secundarios que tengan el valor
false
en la clave secundaria especificada. Si hay varios elementos secundarios con el valorfalse
, se ordenan lexicográficamente por clave. - A continuación, aparecerán los elementos secundarios que tengan el valor
true
en la clave secundaria especificada. Si hay varios elementos secundarios con el valortrue
, se ordenan lexicográficamente por clave. - Luego vienen los elementos secundarios con valor numérico, que se ordenan en sentido ascendente. Si varios elementos secundarios tienen el mismo valor numérico en el nodo secundario especificado, se ordenan según la clave.
- Las strings van después de los números y se ordenan de manera lexicográfica, en sentido ascendente. Si varios elementos secundarios tienen el mismo valor en el nodo secundario especificado, se ordenan de manera lexicográfica según la clave.
- Los objetos quedan en último lugar y se ordenan de manera lexicográfica según su clave, en orden ascendente.
Desvincula objetos de escucha
Los observadores no detienen de forma automática la sincronización de datos cuando dejas un ViewController
. Si un observador no se quita de forma correcta, seguirá sincronizando
datos con la memoria local y retendrá los objetos capturados en el cierre del controlador
del evento, lo que puede causar fugas de memoria. Cuando ya no necesites un observador,
pasa el FIRDatabaseHandle
asociado al método removeObserverWithHandle
para quitarlo.
Cuando agregas un bloque de devoluciones de llamada a una referencia, se muestra FIRDatabaseHandle
.
Estos controladores se pueden usar para quitar el bloque de devoluciones de llamada.
Si se agregaron varios objetos de escucha a la referencia de una base de datos, se llama a cada objeto de escucha cuando surge un evento. Para detener la sincronización de datos en esa ubicación, debes quitar todos los observadores de la ubicación a través del método removeAllObservers
.
Llamar a removeObserverWithHandle
o removeAllObservers
en un objeto de escucha no quita de manera automática los objetos de escucha registrados en estos nodos secundarios; también debes hacer un seguimiento de esas referencias o controladores para quitarlos.