2014-09-05 2 views
1

MongoDb의 자동 증가 필드에 대해이 기사를보고 있습니다. http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/비동기 대량 삽입을 사용하는 MongoDb의 자동 증가 필드

이것은 이론에서는 좋지만 모든 응용 프로그램 호출이 비동기 인 응용 프로그램에서는 작동하지 않습니다. Ps, 임씨는 몽고킨을 사용합니다. 실행될 때이 날 (고전 노드 스타일) 대신 중첩 콜백에 대해 생각합니다 ... 물론 값이 없습니다

var getNextSequence function (name) { 
    db.counters.findAndModify({_id: 'invoiceNr'}, {}, {$inc: {seq: 1}}, {new: true}, function(err, doc) { 
    if (err) { 
     return next(err); 
    } 
    return doc.seq; 
    }); 
}; 

var seq = getNextSequence('invoiceNr'); 
console.log(seq); 

이 (CONSOLE.LOG) :

이 고려
db.counters.findAndModify({_id: 'invoiceNr'}, {}, {$inc: {seq: 1}}, {new: true}, function(err, doc) { 
    if (err) { 
    return next(err); 
    } 
    var seq = getNextSequence('invoiceNr'); 
    // Do something with the seq, like using it when inserting another document. 
}); 

하나의 문서에서는 정상적으로 작동하지만 벌크 삽입 (삽입 할 여러 문서의 배열 전달)을 수행하면 어떻게 작동하는지 알 수 없습니다. 그리고 대량 삽입이 필요합니다.

루프 및 단일 삽입으로 돌아가는 것이 좋은 해결책 인 것 같습니다.

당신은 이것을위한 좋은 해결책이 있습니까?

+0

커스텀'_id' 값을 얻는 것은 당신이 정말로 좋은 경우가 아니면 일반적으로 좋은 아이디어가 아닙니다. 그러나 "벌크"는 무엇을 의미하며 "대량"삽입 할 문서의 수를 항상 알고 있습니까? 적어도 당신은 할 수 있었습니까? –

+0

이것은 _id 필드가 아니지만 동일한 문제가 계속 발생한다는 것을 이해합니다. 이것은 송장 번호를 증가시키기위한 것입니다.저는 사람들보다 제가 회계보다 더 많이 바람직하다는 말을 들었습니다. 대량 삽입 : http://docs.mongodb.org/manual/core/bulk-inserts/ 5 ~ 500 개의 문서를 삽입 할 것입니다. –

+0

하지만 당신은 ** 미리 ** 당신이 미리 처리하는 금액을 알고 있습니까? 따라서 스트림에서 처리하지 않고 실행 중이면 실행하기 전에 항목 수를 여전히 알 수 있습니다. 그것이 본질적으로 내가 분명히하고있는 것입니다. 또한 "대량 API"양식을 원하십니까? mongoskin에서 간단하지는 않지만 가능합니다. –

답변

1

따라서 "업데이트/증가"및 결과 검색 작업이 "원자"작업이므로 문서에서 .findAndModify()을 권장합니다. 물론 한 번에 500 개의 문서를 삽입하는 경우 "get increment the next increment"를 500 번 가져오고 싶지 않습니다. 이는 미친 짓일 수 있기 때문입니다. 그러나 당신이 놓치고있는 개념에 뭔가가 있습니다.

누구를 1 씩 증가시켜야한다고 말했습니까? 간단히 말해, 500 개의 아이템을 삽입했다는 것을 알게되면, 현재 카운터를 501만큼 증가 시켜서 다음 카운터 값을 요구하는 다음 연산이 이미 501만큼 증가 된 값을 얻게하여 그 부분이 괜찮아.

이제 카운터를 500 블록 씩 증가하도록 요청 했으므로 기본적으로 그냥 사용하십시오. 따라서 사용하는 첫 번째 값은 기본적으로 반환 값에서 500을 뺀 값으로 시작하고 실제로 반환 된 값에 삽입을 끝내기를 원한다는 것을 알고 있습니다.

var async = require('async'), 
    mongo = require('mongoskin'), 
    db = mongo.db('mongodb://localhost/test'); 


// The general incrementer 

function getNextSequence(name, increment, callback) { 

    // Handling passing in "increment" as optional 
    var args = Array.prototype.slice.call(arguments, 1); 

    callback = args.pop(); 
    increment = args.length ? args.shift() || 1 : 1; // default 1 

    db.collection('counters').findAndModify(
    { "_id": name }, 
    {}, 
    { "$inc": { "seq": increment } }, 
    { "new": true, "upsert": true }, 
    function(err,doc) { 
     callback(err,doc.seq); 
    } 
); 

} 

// Meat of your insertion logic 

db.collection('target',function(err, collection) { 

    var arrayToInsert = []; // simulating, but 500 items long assumed 
    for (var x=0; x < 500; x++) { 
    arrayToInsert.push({ 
     "x": x 
    }); 
    } 

    var bulk = collection.initializeOrderedBulkOp(); 

    async.waterfall(
    [ 
     function(callback) { 
     getNextSequence('invoiceNo',arrayToInsert.length + 1,callback); 
     }, 
     function(seq,callback) { 
     var current = seq - arrayToInsert.length; 
     var index = 0; 

     async.whilst(
      function() { return index < arrayToInsert.length }, 
      function(callback) { 
      doc = arrayToInsert[index]; 
      doc["invoice"] = current; 
      bulk.insert(doc); 
      index++; 
      current++ 
      callback(); 
      }, 
      function(err) { 
      bulk.execute(callback); 
      } 
     ); 
     } 
    ], 
    function(err,result) { 
     if (err) throw err; 
     // Log BulkWrite result 
     console.log(JSON.stringify(result, undefined, 2)); 
    } 
); 

}); 

글쎄, 그건 기본 시뮬레이터입니다하지만 당신은 아이디어를 얻을해야합니다

그래서 당신은이 같은 일부 코드를합니다. 기본적으로 실제 문서를 삽입 할 때 각 "값"을 삽입하고 사용하려는 항목의 수에 대한 "값"블록을 가져옵니다.

최악의 시나리오? 삽입이 어딘가에 실패했으며 모든 값이 문서에서 끝나지 않았습니다. 그래서? 중요한 점은 카운터가 이미 카운터를 증가시키고 다른 프로세스가 카운터에서 동일한 "값"을 가져올 가능성이 없기 때문입니다.

의견에서 수집 할 수있는 것처럼, 이것이 내가 당신을 이끌어 가고자했던 곳이며 이미 기본을 다뤘을 것입니다. 카운터 1을 1 씩 증가시킬 수는 없으므로 원하는만큼 증가시킵니다.