복붙노트

[MONGODB] 몽구스 자동 증가

MONGODB

몽구스 자동 증가

이 MongoDB의 기사에 따르면, 자동으로 필드를 증가 내가 사용을 카운터 수집 방법을하고자하는 것이 가능하다.

그 예에 대한 문제는 내가 몽고 콘솔을 사용하여 데이터베이스에 데이터를 입력 수천명의 사람들이없는 것입니다. 대신에 나는 몽구스를 사용하는 것을 시도하고있다.

그래서 내 스키마는 다음과 같은 :

var entitySchema = mongoose.Schema({
  testvalue:{type:String,default:function getNextSequence() {
        console.log('what is this:',mongoose);//this is mongoose
        var ret = db.counters.findAndModify({
                 query: { _id:'entityId' },
                 update: { $inc: { seq: 1 } },
                 new: true
               }
        );
        return ret.seq;
      }
    }
});

나는 동일한 데이터베이스에 카운터 수집을 만들고 'ENTITYID'의 _id있는 페이지를 추가했습니다. 여기에서 나는하지 않도록 해당 페이지를 업데이트하고 증가 수를 얻을 수 몽구스를 사용하는 방법입니다.

이 카운터에 대한 스키마는없고 나는이 정말 응용 프로그램에서 사용하는 기업이 아니기 때문에 그것은 그 상태를 유지하고 싶습니다. 그것은 단지 자동 증가 필드에 스키마 (들)에 사용되어야한다.

해결법

  1. ==============================

    1.다음은 몽구스의 자동 증가 필드를 구현하는 방법을 예입니다 :

    다음은 몽구스의 자동 증가 필드를 구현하는 방법을 예입니다 :

    var CounterSchema = Schema({
        _id: {type: String, required: true},
        seq: { type: Number, default: 0 }
    });
    var counter = mongoose.model('counter', CounterSchema);
    
    var entitySchema = mongoose.Schema({
        testvalue: {type: String}
    });
    
    entitySchema.pre('save', function(next) {
        var doc = this;
        counter.findByIdAndUpdate({_id: 'entityId'}, {$inc: { seq: 1} }, function(error, counter)   {
            if(error)
                return next(error);
            doc.testvalue = counter.seq;
            next();
        });
    });
    
  2. ==============================

    2.다음과 같이 몽구스 - 자동 증가 패키지를 사용할 수 있습니다 :

    다음과 같이 몽구스 - 자동 증가 패키지를 사용할 수 있습니다 :

    var mongoose      = require('mongoose');
    var autoIncrement = require('mongoose-auto-increment');
    
    /* connect to your database here */
    
    /* define your CounterSchema here */
    
    autoIncrement.initialize(mongoose.connection);
    CounterSchema.plugin(autoIncrement.plugin, 'Counter');
    var Counter = mongoose.model('Counter', CounterSchema);
    

    한 번만 자동 증가를 초기화해야합니다.

  3. ==============================

    3.가장 투표 대답은 작동하지 않습니다. 이 수정 프로그램입니다 :

    가장 투표 대답은 작동하지 않습니다. 이 수정 프로그램입니다 :

    var CounterSchema = new mongoose.Schema({
        _id: {type: String, required: true},
        seq: { type: Number, default: 0 }
    });
    var counter = mongoose.model('counter', CounterSchema);
    
    var entitySchema = mongoose.Schema({
        sort: {type: String}
    });
    
    entitySchema.pre('save', function(next) {
        var doc = this;
        counter.findByIdAndUpdateAsync({_id: 'entityId'}, {$inc: { seq: 1} }, {new: true, upsert: true}).then(function(count) {
            console.log("...count: "+JSON.stringify(count));
            doc.sort = count.seq;
            next();
        })
        .catch(function(error) {
            console.error("counter error-> : "+error);
            throw error;
        });
    });
    

    옵션 매개 변수는 당신에게 업데이트의 결과를 제공하고 존재하지 않는 경우 새 문서를 작성합니다. 여기 공식 문서를 확인할 수 있습니다.

    그리고 당신은 정렬 된 인덱스를해야하는 경우이 문서를 확인

  4. ==============================

    4.복수 응답을 결합 그래서, 이것은 내가 사용 결국 무엇을 :

    복수 응답을 결합 그래서, 이것은 내가 사용 결국 무엇을 :

    counterModel.js

    var mongoose = require('mongoose');
    var Schema = mongoose.Schema;
    
    const counterSchema = new Schema(
      {
      _id: {type: String, required: true},
      seq: { type: Number, default: 0 }
      }
    );
    
    counterSchema.index({ _id: 1, seq: 1 }, { unique: true })
    
    const counterModel = mongoose.model('counter', counterSchema);
    
    const autoIncrementModelID = function (modelName, doc, next) {
      counterModel.findByIdAndUpdate(        // ** Method call begins **
        modelName,                           // The ID to find for in counters model
        { $inc: { seq: 1 } },                // The update
        { new: true, upsert: true },         // The options
        function(error, counter) {           // The callback
          if(error) return next(error);
    
          doc.id = counter.seq;
          next();
        }
      );                                     // ** Method call ends **
    }
    
    module.exports = autoIncrementModelID;
    

    myModel.js

    var mongoose = require('mongoose');
    var Schema = mongoose.Schema;
    
    const autoIncrementModelID = require('./counterModel');
    
    const myModel = new Schema({
      id: { type: Number, unique: true, min: 1 },
      createdAt: { type: Date, default: Date.now },
      updatedAt: { type: Date },
      someOtherField: { type: String }
    });
    
    myModel.pre('save', function (next) {
      if (!this.isNew) {
        next();
        return;
      }
    
      autoIncrementModelID('activities', this, next);
    });
    
    module.exports = mongoose.model('myModel', myModel);
    
  5. ==============================

    5.나는이 이미 답변을 많이 가지고 알지만, IMO 짧고 쉽게 이해할 수 내 솔루션을 공유하는 것입니다 :

    나는이 이미 답변을 많이 가지고 알지만, IMO 짧고 쉽게 이해할 수 내 솔루션을 공유하는 것입니다 :

    // Use pre middleware
    entitySchema.pre('save', function (next) {
    
        // Only increment when the document is new
        if (this.isNew) {
            entityModel.count().then(res => {
                this._id = res; // Increment count
                next();
            });
        } else {
            next();
        }
    });
    

    확인 entitySchema._id이 유형이 있는지 확인 : 번호. 몽구스 버전 : 5.0.1.

  6. ==============================

    6.내가 추가 모듈을했다, 그래서 (... 등의 server.js에 하나 개의 I 사용에서 떨어져 MongoDB의 연결을 초기화, 여분의 dependencie) 어떤 플러그인을 사용 완하지 않았다, 내가 어떤 스키마에서 사용할 수 있으며, 당신은 DB에서 문서를 제거 할 경우에도, 나는 고려 중이 야.

    내가 추가 모듈을했다, 그래서 (... 등의 server.js에 하나 개의 I 사용에서 떨어져 MongoDB의 연결을 초기화, 여분의 dependencie) 어떤 플러그인을 사용 완하지 않았다, 내가 어떤 스키마에서 사용할 수 있으며, 당신은 DB에서 문서를 제거 할 경우에도, 나는 고려 중이 야.

    module.exports = async function(model, data, next) {
        // Only applies to new documents, so updating with model.save() method won't update id
        // We search for the biggest id into the documents (will search in the model, not whole db
        // We limit the search to one result, in descendant order.
        if(data.isNew) {
            let total = await model.find().sort({id: -1}).limit(1);
            data.id = total.length === 0 ? 1 : Number(total[0].id) + 1;
            next();
        };
    };
    

    그리고 그것을 사용하는 방법 :

    const autoincremental = require('../modules/auto-incremental');
    
    Work.pre('save', function(next) {
        autoincremental(model, this, next);
        // Arguments:
        // model: The model const here below
        // this: The schema, the body of the document you wan to save
        // next: next fn to continue
    });
    
    const model = mongoose.model('Work', Work);
    module.exports = model;
    

    당신을 도움이되기를 바랍니다.

    (이 잘못되면, 아닌 전문가 나는이 아무 문제가되지했습니다. 말해,하지만하시기 바랍니다)

  7. ==============================

    7.다른 방법은 당신이 몽구스에 의해 주어진 외부 패키지를 사용할 수있다. (이해하기 쉽게)

    다른 방법은 당신이 몽구스에 의해 주어진 외부 패키지를 사용할 수있다. (이해하기 쉽게)

    몽구스 순서 플러그인

  8. ==============================

    8.대답은 문서가 이미 (어떤 종류)를 _id 필드가 있더라도 순서를 증가 것으로 보인다. 기존 문서를 업데이트 할 '저장'경우에 해당 될 것이다. 아니?

    대답은 문서가 이미 (어떤 종류)를 _id 필드가 있더라도 순서를 증가 것으로 보인다. 기존 문서를 업데이트 할 '저장'경우에 해당 될 것이다. 아니?

    내가 옳다 경우, 다음 () this._id 경우 전화 싶어! == 0

    몽구스 문서 슈퍼 이것에 대해 명확하지 않다. 내부적으로 업데이트 유형의 쿼리를하고있는 경우 ( '저장'을 호출 할 수 없습니다 사전.

    설명

    '저장'을 사전 방법은 참으로 업데이트에서 호출되어 나타납니다.

    나는 당신이 불필요하게 당신의 순서를 증가 할 생각하지 않습니다. 그것은 당신에게 쿼리 및 폐기물 시퀀스 번호를 요한다.

  9. ==============================

    9.나는 cluny85 및 @edtech @ 함께 사용합니다. 그러나 나는 완료되지 마감이 문제를 않습니다.

    나는 cluny85 및 @edtech @ 함께 사용합니다. 그러나 나는 완료되지 마감이 문제를 않습니다.

    counterModel.findByIdAndUpdate ({_ ID : '원조'}, {$ INC : {SEQ : 1}} 기능 (오류, 카운터) { 그러나 함수에서 "(저장 ... ') 문서를 저장 한 후 업데이트 카운터 마무리 한 후 응답 사전. 나는 문서에 카운터를 업데이트하지 않도록.

    다시 확인 모든 당신을 answer.Thank하십시오.

    죄송합니다. 내가 코멘트를 추가 할 수 없습니다. 내가 초보자이기 때문에.

  10. ==============================

    10.

    var CounterSchema = Schema({
        _id: { type: String, required: true },
        seq: { type: Number, default: 0 }
    });
    var counter = mongoose.model('counter', CounterSchema);
    
    var entitySchema = mongoose.Schema({
        testvalue: { type: String }
    });
    
    entitySchema.pre('save', function(next) {
        if (this.isNew) {
            var doc = this;
            counter.findByIdAndUpdate({ _id: 'entityId' }, { $inc: { seq: 1 } }, { new: true, upsert: true })
                .then(function(count) {
                    doc.testvalue = count.seq;
                    next();
                })
                .catch(function(error) {
                    throw error;
                });
        } else {
            next();
        }
    });
    
  11. ==============================

    11.여기 제안입니다.

    여기 제안입니다.

    const autoIncrementSchema = new Schema({
        name: String,
        seq: { type: Number, default: 0 }
    });
    
    const AutoIncrement = mongoose.model('AutoIncrement', autoIncrementSchema);
    

    이제 각 필요한 스키마, 후크 저장 사전-A를 추가합니다.

    예를 들어, 컬렉션 이름은 테스트입니다하자

    schema.pre('save', function preSave(next) {
        const doc = this;
        if (doc.isNew) {
             const nextSeq = AutoIncrement.findOneAndUpdate(
                 { name: 'Test' }, 
                 { $inc: { seq: 1 } }, 
                 { new: true, upsert: true }
             );
    
             nextSeq
                 .then(nextValue => doc[autoIncrementableField] = nextValue)
                 .then(next);
        }
        else next();
     }
    

    findOneAndUpdate은 원자 동작이기 때문에, 두 개의 업데이트 동일한 서열 값을 반환 할 것이다. 따라서 귀하의 삽입 각에 관계없이 동시 삽입의 수의 증가 서열을 얻을 것이다. 또한이 숫자 타입에 한정되지 않고, 더욱 복잡한 로직 자동 증분 및 자동 증가 순서로 확장 될 수있다

    이것은 테스트 코드가 아닙니다. 내가 몽구스위한 플러그인을 만들 때까지 테스트 당신은 사용하기 전에.

    업데이트 나는이 플러그인 관련 접근 방식을 구현 것을 발견했다.

  12. ==============================

    12.나는 대답의 모든 (주관적 및 객관적으로) 좋은 부품을 결합하고,이 코드를 내놓았다했습니다 :

    나는 대답의 모든 (주관적 및 객관적으로) 좋은 부품을 결합하고,이 코드를 내놓았다했습니다 :

    const counterSchema = new mongoose.Schema({
        _id: {
            type: String,
            required: true,
        },
        seq: {
            type: Number,
            default: 0,
        },
    });
    
    // Add a static "increment" method to the Model
    // It will recieve the collection name for which to increment and return the counter value
    counterSchema.static('increment', async function(counterName) {
        const count = await this.findByIdAndUpdate(
            counterName,
            {$inc: {seq: 1}},
            // new: return the new value
            // upsert: create document if it doesn't exist
            {new: true, upsert: true}
        );
        return count.seq;
    });
    
    const CounterModel = mongoose.model('Counter', counterSchema);
    
    
    entitySchema.pre('save', async function() {
        // Don't increment if this is NOT a newly created document
        if(!this.isNew) return;
    
        const testvalue = await CounterModel.increment('entity');
        this.testvalue = testvalue;
    });
    

    이 방법의 장점 중 하나는 모든 카운터 관련 로직이 분리되어 있다는 점이다. 당신은 별도의 파일에 저장하고 CounterModel를 가져 오는 여러 모델을 사용할 수 있습니다.

    당신이 _id 필드를 증가하기 위하여려고하는 경우에, 사용은 스키마에 정의를 추가해야합니다 :

    const entitySchema = new mongoose.Schema({
        _id: {
            type: Number,
            alias: 'id',
            required: true,
        },
        <...>
    });
    
  13. from https://stackoverflow.com/questions/28357965/mongoose-auto-increment by cc-by-sa and MIT license