156 votos

¿Cómo actualizar una "matriz de objetos" con Firestore?

Actualmente estoy probando Firestore, y me he quedado atascado en algo muy simple: "actualizar un array (también conocido como un subdocumento)".

La estructura de mi base de datos es muy simple. Por ejemplo:

proprietario: "John Doe",
compartidoCon:
  [
    {who: "first@test.com", when:timestamp},
    {who: "another@test.com", when:timestamp},
  ],

Estoy intentando (sin éxito) agregar nuevos registros al array de objetos compartidoCon.

He intentado:

// Con SET
firebase.firestore()
.collection('proprietario')
.doc(docID)
.set(
  { compartidoCon: [{ who: "tercero@test.com", when: new Date() }] },
  { merge: true }
)

// Con UPDATE
firebase.firestore()
.collection('proprietario')
.doc(docID)
.update({ compartidoCon: [{ who: "tercero@test.com", when: new Date() }] })

Ninguno funciona. Estas consultas sobrescriben mi array.

La respuesta puede ser simple, pero no he podido encontrarla...

1 votos

Hola, ¿lo resolviste? Todavía no puedo encontrar una respuesta.

0 votos

Para Android, es tan simple como ¿Cómo actualizar un array de objetos en Firestore?.

197voto

Doug Galante Puntos 771

Firestore ahora tiene dos funciones que te permiten actualizar un array sin reescribir todo.

Enlace: https://firebase.google.com/docs/firestore/manage-data/add-data, específicamente https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array

Actualizar elementos en un array

Si tu documento contiene un campo de array, puedes usar arrayUnion() y arrayRemove() para agregar y quitar elementos. arrayUnion() agrega elementos a un array pero solo aquellos que no están presentes. arrayRemove() remueve todas las instancias de cada elemento dado.

93 votos

¿Existe alguna forma de actualizar un índice específico del arreglo?

1 votos

¿Cómo usar esta función de actualización de matriz con "react-native-firebase"? (No encuentro esto en la documentación oficial de react-native-firebase)

7 votos

@ArturCarvalho No, la razón se explica en este video youtube.com/…

103voto

hatboysam Puntos 1191

Editar 08/13/2018: Ahora hay soporte para operaciones nativas de arrays en Cloud Firestore. Ver la respuesta de Doug abajo.


Actualmente no hay forma de actualizar un solo elemento de un array (o agregar/eliminar un solo elemento) en Cloud Firestore.

Este código aquí:

firebase.firestore()
.collection('proprietary')
.doc(docID)
.set(
  { sharedWith: [{ who: "third@test.com", when: new Date() }] },
  { merge: true }
)

Esto indica establecer el documento en proprietary/docID de manera que sharedWith = [{ who: "third@test.com", when: new Date() } pero sin afectar ninguna propiedad de documento existente. Es muy similar a la llamada de update() que proporcionaste, sin embargo la llamada de set() creará el documento si no existe mientras que la llamada de update() fallará.

Entonces tienes dos opciones para lograr lo que quieres.

Opción 1 - Establecer todo el array

Llama a set() con el contenido completo del array, lo cual requerirá leer primero los datos actuales de la base de datos. Si te preocupa las actualizaciones concurrentes, puedes hacer todo esto en una transacción.

Opción 2 - Usar una subcolección

Puedes hacer que sharedWith sea una subcolección del documento principal. Entonces agregar un solo ítem se vería así:

firebase.firestore()
  .collection('proprietary')
  .doc(docID)
  .collection('sharedWith')
  .add({ who: "third@test.com", when: new Date() })

Por supuesto, esto viene con nuevas limitaciones. No podrías realizar consultas a documentos basadas en con quién están compartidos, ni podrías obtener el documento y todos los datos de sharedWith en una sola operación.

10 votos

Esto es tan frustrante... pero gracias por hacerme saber que no estoy volviéndome loco.

63 votos

Esto es una gran desventaja, Google tiene que solucionarlo lo antes posible.

5 votos

La respuesta de @DougGalante indica que esto ha sido arreglado. Usa el método arrayUnion.

28voto

Veeresh Devireddy Puntos 678

Aquí tienes el último ejmplo de la documentación de Firestore:

firebase.firestore.FieldValue.ArrayUnion

var washingtonRef = db.collection("cities").doc("DC");

// Añadir atómicamente una nueva región al campo "regions" de tipo array.
washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});

// Eliminar atómicamente una región del campo "regions" de tipo array.
washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayRemove("east_coast")
});

1 votos

@nifCody, esto de hecho agregará un nuevo elemento de cadena "greater_virginia" a un array existente "regions". Lo he probado con éxito, y definitivamente no agregando "object". Está en sincronía con la pregunta tal como está afirmada: "push new records".

22voto

Gabriel McCallin Puntos 101

Puedes utilizar una transacción (https://firebase.google.com/docs/firestore/manage-data/transactions) para obtener el array, agregar elementos y luego actualizar el documento:

    const reserva = { some: "data" };
    const userRef = this.db.collection("users").doc(userId);

    this.db.runTransaction(transaction => {
        // Este código puede ejecutarse varias veces si hay conflictos.
        return transaction.get(userRef).then(doc => {
            if (!doc.data().bookings) {
                transaction.set({
                    bookings: [reserva]
                });
            } else {
                const bookings = doc.data().bookings;
                bookings.push(reserva);
                transaction.update(userRef, { bookings: bookings });
            }
        });
    }).then(function () {
        console.log("¡Transacción realizada con éxito!");
    }).catch(function (error) {
        console.log("Fallo en la transacción: ", error);
    });

1 votos

En el enunciado if deberías cambiarlo por esto, porque te falta el documentReference agregue userRef como se muestra: transaction.set(userRef, { reservas: [reserva] });

0 votos

Esto reescribirá todo el array

8voto

Guru Puntos 96

Perdón por llegar tarde a la fiesta, pero Firestore lo resolvió desde agosto de 2018. Entonces, si todavía estás buscando eso, aquí tienes todas las cuestiones resueltas con respecto a los arrays.

https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.htmlEntrada de blog oficial

array-contains, arrayRemove, arrayUnion para verificar, eliminar y actualizar arrays. Espero que te sea útil.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X