¿Para qué sirve el tipo de datos 'Referencia' de Firebase Firestore?

189

Solo estoy explorando el nuevo Firebase Firestore y contiene un tipo de datos llamado reference. No me queda claro qué hace esto.

  • ¿Es como una clave foránea?
  • ¿Se puede usar para apuntar a una colección que se encuentra en otro lugar?
  • Si referencees una referencia real, ¿puedo usarla para consultas? Por ejemplo, ¿puedo tener una referencia que apunte directamente al usuario, en lugar de almacenar el ID de usuario en un campo de texto? ¿Y puedo usar esta referencia de usuario para realizar consultas?
Jürgen Brandstetter
fuente
18
Creo que este video del equipo de Firebase lo desglosa para usted: youtube.com/watch?v=Elg2zDVIcLo (ver desde 4:36)
Adarsh

Respuestas:

91

Las referencias son muy parecidas a las claves externas.

Los SDK publicados actualmente no pueden almacenar referencias a otros proyectos. Dentro de un proyecto, las referencias pueden apuntar a cualquier otro documento en cualquier otra colección.

Puede utilizar referencias en consultas como cualquier otro valor: para filtrar, ordenar y para paginación (startAt / startAfter).

A diferencia de las claves foráneas en una base de datos SQL, las referencias no son útiles para realizar uniones en una sola consulta. Puede usarlos para búsquedas dependientes (que parecen unidas), pero tenga cuidado porque cada salto dará como resultado otro viaje de ida y vuelta al servidor.

Gil Gilbert
fuente
9
Por favor, ¿puedes compartir posibles casos de uso? ¿Es posible consultar campos en esa referencia? Por ejemplo, tengo una friendscolección con todos mis amigos ( friends/myId). Luego, hago referencia a este documento en el friendscampo de otro documento ( group/groupId). Me gustaría mostrar sólo mis amigos que están en ese grupo, haciendo algo como esto: where('friends.myId', '==', true).
Will
108
Por cierto, podría ser útil actualizar los documentos para incluir un ejemplo de agregar un tipo de referencia.
Será
11
¿No puedo encontrar ninguna información sobre esto? Esto va a cambiar mi estructura de base de datos completa, lo que necesito saber más ...
Ruben
3
¿Tiene un ejemplo (preferiblemente en Swift) sobre cómo consultar utilizando la referencia? en este momento, puedo hacerlo almacenando el uid sin procesar como una cadena, pero eso no parece correcto.
Mickey Cheong
66
Necesito cambiar todos mis tipos de referencia a cadenas porque la consulta siempre fallará con un tipo de referencia. Literalmente, no puedo encontrar nada sobre cómo consultar por tipo de referencia :( si alguien descubre cómo consultar por tipos de referencia, hágamelo saber ...
Sam Trent
133

Agregando a continuación lo que funcionó para mí usando referencias en Firestore.

Como dicen las otras respuestas, es como una clave externa. Sin embargo, el atributo de referencia no devuelve los datos del documento de referencia. Por ejemplo, tengo una lista de productos, con una referencia de UserRef como uno de los atributos del producto. Obtener la lista de productos me da la referencia del usuario que creó ese producto. Pero no me da los detalles del usuario en esa referencia. He usado otro back-end como servicios con punteros antes que tienen un indicador "populate: true" que devuelve los detalles del usuario en lugar de solo la identificación de referencia del usuario, lo cual sería genial tener aquí (con suerte, una mejora futura )

A continuación se muestra un código de ejemplo que utilicé para establecer la referencia, así como obtener la colección de la lista de productos y luego obtener los detalles del usuario a partir de la identificación de referencia del usuario dada.

Establecer una referencia en una colección:

let data = {
  name: 'productName',
  size: 'medium',
  userRef: db.doc('users/' + firebase.auth().currentUser.uid)
};
db.collection('products').add(data);

Obtenga una colección (productos) y todas las referencias en cada documento (detalles del usuario):

db.collection('products').get()
    .then(res => {
      vm.mainListItems = [];
      res.forEach(doc => {
        let newItem = doc.data();
        newItem.id = doc.id;
        if (newItem.userRef) {
          newItem.userRef.get()
          .then(res => { 
            newItem.userData = res.data() 
            vm.mainListItems.push(newItem);
          })
          .catch(err => console.error(err));
        } else {
          vm.mainListItems.push(newItem);  
        }

      });
    })
    .catch(err => { console.error(err) });

Espero que esto ayude

Ben Cochrane
fuente
3
¡Gracias por compartir! Creo que hay un error tipográfico en la primera línea de Obtener parte y debería estarlo db.collection('products').get(). ¿Has intentado obtener un usuario directamente? Supongo que newItem.userRef.get()debería funcionar en lugar dedb.collection("users").doc(newItem.userRef.id).get()
Sergey Nefedyev
53
En primer lugar gracias por el ejemplo. Espero que agreguen un "poblado: verdadero" para el futuro. De lo contrario, guardar una referencia es algo inútil. Lo mismo podría haberse hecho simplemente guardando el uidy la referencia a través de él.
Jürgen Brandstetter
44
Gracias por el ejemplo! Pero, ¿cuál es el punto de almacenar el tipo de referencia si no hay una opción de "rellenar" cuando consultamos el documento? Si hay una opción de rellenar que alguien conoce, por favor hágamelo saber.
Harshil Shah
18
De hecho, no es como una clave foránea. Para mí, básicamente no hace nada: ¿qué sentido tiene tener referencesi no podemos usarlo como una verdadera clave externa debería funcionar?
jean d'arme
14
Entonces, la única ventaja de a referencesobre a stringes que puede recurrir get()directamente a la referencia. No es muy útil todavía. ¡Espero que agreguen una opción para completar automáticamente las referencias con los objetos correspondientes!
morgler
16

Para aquellos que buscan una solución Javascript para realizar consultas por referencia, el concepto es que debe usar un objeto 'referencia de documento' en la declaración de consulta

teamDbRef = db.collection('teams').doc('CnbasS9cZQ2SfvGY2r3b'); /* CnbasS9cZQ2SfvGY2r3b being the collection ID */
//
//
db.collection("squad").where('team', '==', teamDbRef).get().then((querySnapshot) => {
  //
}).catch(function(error) {
  //
});

(Felicitaciones a la respuesta aquí: https://stackoverflow.com/a/53141199/1487867 )

Aswin Kumar
fuente