2

J'essaye de créer un WriteBatch pour garder le contrôle d'une de mes références dinamic dans ma base de données. Mon application a un modèle simple User-Follow-Post-Feed où je veux que mon utilisateur voit dans son flux les messages de tous les utilisateurs qu'il suit. Ce que je fais après la recherche sur Firebase exemples (comme Firefeed) et beaucoup de messages sur StackOverflow.Exécuter plus de 500 opérations à la fois dans Firestore Database

L'idée optimale est de garder un chemin (collection dans ce cas) où je stocke le Ids des messages que mon utilisateur devrait voir dans son flux, ce qui signifie garder le contrôle de la copie et supprimer tous les messages de tous les utilisateurs qu'il suivre/ne plus suivre.

J'ai fait mon Cloud functions pour garder cela de manière atomique, et tout fonctionne bien, mais quand j'ai essayé de faire un test massif, en ajoutant plus de 5000 messages pour un utilisateur essayant de le suivre (à la recherche de voir comment beaucoup de temps prendrait le Cloud function), j'ai vu que les lots ont une limite de 500 opérations. Donc ce que j'ai fait est de diviser mes 5000 identifiants dans plusieurs petites listes et d'exécuter un lot par liste, ne dépassant jamais la limite de 500.

Mais même en le faisant de cette façon, je reçois toujours une erreur que I can't do more than 500 operations in a single commit, je ne sais pas si peut-être parce que les lots s'exécutent en même temps, ou pourquoi. Je pense que je peux peut-être concaténer l'un après l'autre, et éviter de les exécuter tous en même temps. Mais j'ai toujours des problèmes avec ça. Voilà donc la raison de ma question.

Voici ma méthode:

fun updateFeedAfterUserfollow(postIds: QuerySnapshot, userId: String) { 
     //If there is no posts from the followed user, return 
     if (postIds.isEmpty) return 
     val listOfPostsId = postIds.map { it.id } 
     val mapOfInfo = postIds.map { it.id to it.toObject(PublicUserData::class.java) }.toMap() 

     //Get User ref 
     val ref = firestore.collection(PRIVATE_USER_DATA).document(userId).collection(FEED) 
     //Split the list in multiple list to avoid the max 500 operations per batch 
     val idsPartition = Lists.partition(listOfPostsId, 400) 

     //Create a batch with max 400 operations and execute it until the whole list have been updated 
     idsPartition.forEach { Ids -> 
      val batch = firestore.batch().also { batch -> 
       Ids.forEach { id -> batch.set(ref.document(id), mapOfInfo[id]!!) } 
      } 
      batch.commit().addOnCompleteListener { 
       if (it.isSuccessful) 
        Grove.d { "Commit updated successfully" } 
       else Grove.d { "Commit fail" } 
      } 
     } 
    } 

espoir que quelqu'un sera en mesure de me donner un coup de main. Merci beaucoup pour votre temps!

+0

Quel est le message d'erreur que vous obtenez? –

+0

Quelle était votre solution finale? – 22Ryann

Répondre

1

enfin le problème a été causé parce que je suis en train de réaliser cette opérations par lots dans une transaction, qui agit également comme un lot à la fin. C'est pourquoi même si je produisais des lots pour 400 références, ces instances ont été créées à l'intérieur d'une transaction et cela compte comme une seule grosse transaction qui dépasse la limite de 500. J'ai fait quelques modifications et implémenté sur un dépôt sur mon github.

//Generate the right amount of batches 
    const batches = _.chunk(updateReferences, MAX_BATCH_SIZE) 
     .map(dataRefs => { 
      const writeBatch = firestoreInstance.batch(); 
      dataRefs.forEach(ref => { 
       writeBatch.update(ref, 'author', newAuthor); 
      }); 
      return writeBatch.commit(); 
     }); 

Il est sur tapuscrit writed, mais vous comprendrez qu'il est sûr: https://github.com/FrangSierra/firestore-cloud-functions-typescript/blob/master/functions/src/atomic-operations/index.ts