2017-04-04 2 views
3
나는 현재 하나를 사용하여 DB를 하나 upserted하는 JS 개체의 목록을 구문 분석하고

에 데이터베이스에 upserting :약속 및 대량

return promise.map(list, 
    return parseItem(item) 
     .then(upsertSingleItemToDB) 
    ).then(all finished!) 

문제는 그 때 목록 크기가 매우 커져서 (~ 3000 항목), 병렬로 모든 항목을 구문 분석하면 너무 많은 메모리가 필요합니다. 약속 라이브러리에 동시성 제한을 추가하고 메모리가 부족한 경우 (/ guard)는 정말 쉽지 않았습니다.

하지만 mongodb가 bulkWrite 기능을 제공하기 때문에 db upserts도 최적화하고 싶습니다. 한 번에 모든 항목을 구문 분석하고 대량으로 작성할 수 없으므로 원래 개체 목록을 약속과 함께 구문 분석되는 작은 집합으로 분할 한 다음 해당 집합의 결과 배열을 promisified bulkWrite로 전달해야합니다. 목록 항목 인 경우 나머지 세트에 대해 반복됩니다.

저는 약속의 작은 세트를 구조화 할 수있는 방법을 고심하고 있습니다. 그래서 Promise.all ([set1Bulk] [set2Bulk]) 같은 시간에 한 세트의 parseSomeItems-BulkUpsertThem 만 수행합니다.), 어디 set1Bulk 병렬 파서 약속 다른 배열입니다?), 모든 의사 코드 도움을 주시면 감사하겠습니다 (하지만 내가 차이를 만드는 경우 사용하고 있습니다). 몽구스를 사용하여 기본 nodejs-MongoDB의 드라이버 경우 ​​

답변

1

그것은, 다음과 같이 보일 수 있습니다

const saveParsedItems = items => ItemCollection.collection.bulkWrite(// accessing underlying driver 
 
    items.map(item => ({ 
 
     updateOne: { 
 
      filter: {id: item.id}, // or any compound key that makes your items unique for upsertion 
 
      upsert: true, 
 
      update: {$set: item} // should be a key:value formatted object 
 
     } 
 
    })) 
 
); 
 

 

 
const parseAndSaveItems = (items, offset = 0, limit = 3000) => { // the algorithm for retrieving items in batches be anything you want, basically 
 
    const itemSet = items.slice(offset, limit); 
 
    
 
    return Promise.all(
 
    itemSet.map(parseItem) // parsing all your items first 
 
) 
 
    .then(saveParsedItems) 
 
    .then(() => { 
 
     const newOffset = offset + limit; 
 
     if (items.length >= newOffset) { 
 
     return parseAndSaveItemsSet(items, newOffset, limit); 
 
     } 
 
     
 
     return true; 
 
    }); 
 
}; 
 

 
return parseAndSaveItems(yourItems);

+1

아 물론 재귀! 내 뇌가 약속의 긴 사슬을 만들려고 서클에서 뛰어 다니고있었습니다 ... 감사합니다. 무리를지었습니다. 이것은 정확히 내가 찾고 있었던 것입니다. <3 – usagidon

1

첫 번째 대답이 완료 보인다. 그러나 여기에 마음에 떠오른 다른 생각들이 있습니다.

해킹으로 다음 쓰기 작업이 수행되기 전에 쓰기 작업의 콜백에서 시간 초과 함수를 호출 할 수 있습니다. 이렇게하면 CPU와 메모리에 호출이 중단 될 수 있습니다. 호출간에 1 밀리 초를 추가하더라도 총 3000 개의 쓰기 객체가있는 경우에만 3 초가 추가됩니다.

또는 insertObject 배열을 세그먼트로 묶어 자신의 대량 작성자에게 보낼 수 있습니다.