2

WriteBatch을 작성하여 데이터베이스에서 내 다이나믹 참조 중 하나를 제어하려고합니다. 내 앱에는 사용자가 소식을받는 모든 사용자의 소식을 내 사용자가보고 싶어하는 간단한 User-Follow-Post-Feed 모델이 있습니다. 내가 Firebase 예제 (Firefeed)와 StackOverflow에 많은 게시물에 대한 연구를하고 있습니다.Firestore 데이터베이스에서 한 번에 500 개 이상의 작업 실행

최적의 아이디어는 내 사용자가 피드에서 볼 수있는 게시물의 Ids을 저장하는 경로 (이 경우 collection)를 유지하는 것입니다. 즉, 사용자가 볼 수있는 모든 게시물을 복사 및 삭제한다는 의미입니다 팔로우/언 폴링.

나는이 방법을 원자 단위로 유지하기 위해 내 Cloud functions을 만들었지 만 모든 것이 잘 작동하지만, 대규모 테스트를 수행 할 때 사용자를 위해 5000 개 이상의 게시물을 추가하여 그를 따르려고했다. 많은 시간 (Cloud function이 걸릴 것입니다), 나는 그 배치가 500 작업의 한계를 가지고있는 것을 보았습니다. 그래서 내가 한 것은 나의 작은 ID를 여러 개의 작은 목록으로 나누고 목록 당 하나의 배치를 실행하며 결코 500 한계를 초과하지 않습니다.

그러나 이런 식으로해도 여전히 오류가 발생합니다. I can't do more than 500 operations in a single commit, 일괄 처리가 동시에 실행되고 있는지, 또는 이유가 무엇인지 모릅니다. 어쩌면 하나씩 연쇄 적으로 연결하여 한꺼번에 실행하지 않아도된다고 생각합니다. 그러나 나는 아직도 그것으로 약간 말썽이있다. 그래서 그것이 내 질문의 이유입니다. 누군가가 나에게 손을 줄 수있을 것

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" } 
      } 
     } 
    } 

희망 :

여기 내 방법입니다. 시간 내 주셔서 감사합니다.

+0

당신이 얻을 오류 메시지가 무엇입니까? –

+0

최종 솔루션은 무엇입니까? – 22Ryann

답변

1

마지막으로 문제는 결국이 배치 작업을 트랜잭션 내부에서 실현하려고했기 때문에 발생했습니다. 트랜잭션은 결국 배치와 같은 역할을합니다. 그렇기 때문에 각 400 개의 참조에 대해 일괄 처리를 생성하는 경우에도이 인스턴스는 트랜잭션 내부에서 생성되었으며 500 개의 제한을 초과하는 단일 큰 트랜잭션처럼 계산됩니다. 몇 가지 변경 작업을 수행하고 내 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(); 
     }); 

그것은 타이프에 writed,하지만 당신은 확실히 그것을 이해합니다 https://github.com/FrangSierra/firestore-cloud-functions-typescript/blob/master/functions/src/atomic-operations/index.ts