Mongoose 자동 증분
이 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;
}
}
});
같은 데이터베이스에 카운터 컬렉션을 만들고 _id가 'entityId'인 페이지를 추가했습니다.여기서부터는 mongoose를 사용하여 페이지를 업데이트하고 증가하는 숫자를 얻는 방법을 잘 모르겠습니다.
카운터에 대한 스키마가 없으며 응용 프로그램에서 실제로 사용하는 엔티티가 아니기 때문에 그대로 유지했으면 합니다.자동 증분을 위해 스키마 필드에서만 사용해야 합니다.
다음은 Mongoose에서 자동 증분 필드를 구현하는 방법의 예입니다.
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();
});
});
사용할 수 있습니다.mongoose-auto-increment
패키지는 다음과 같습니다.
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);
당신은 만하됩다니면초기만 .autoIncrement
한번만.
여러 답변을 결합하여 사용하게 된 것은 다음과 같습니다.
counterModel
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);
가장 많이 투표된 답은 효과가 없습니다.해결책은 다음과 같습니다.
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;
});
});
옵션 매개변수는 업데이트 결과를 제공하며, 문서가 없는 경우 새 문서를 작성합니다.당신은 여기서 공식 문서를 확인할 수 있습니다.
정렬된 색인이 필요하면 이 문서를 확인하십시오.
차려!
Hammerbot과 dan-dascalescu가 지적했듯이 문서를 제거하면 이는 작동하지 않습니다.
가 가인 하면 3개의 문서를 삽입할 수 .
1
,2
그리고.3
제합니다를 합니다.2
그리고 그것이 얻을 다른 새로운 것을 삽입합니다.3
이미 사용 중인 ID!
문서를 제거하지 않는 경우 다음을 수행합니다.
이것이 이미 많은 답을 가지고 있다는 것을 알지만, 저는 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
가지다type:Number
몽구스:5.0.1
.
이 문제는 충분히 복잡하고 충분한 함정이 있기 때문에 테스트된 몽구스 플러그인에 의존하는 것이 가장 좋습니다.
http://plugins.mongoosejs.io/, 의 수많은 "자동 증가" 플러그인 중에서 가장 잘 유지되고 문서화된 것은 mongoose 시퀀스입니다.
저는 (객관적이고 객관적으로) 답변의 모든 좋은 부분을 결합하여 다음과 같은 코드를 만들었습니다.
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,
},
<...>
});
test.pre("save",function(next){
if(this.isNew){
this.constructor.find({}).then((result) => {
console.log(result)
this.id = result.length + 1;
next();
});
}
})
플러그인(추가 종속성, server.js 등에서 사용하는 플러그인을 제외한 mongodb 연결 초기화 등)을 사용하고 싶지 않았기 때문에 추가 모듈을 수행했습니다. 어떤 스키마에서도 사용할 수 있고, 심지어 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;
도움이 되길 바랍니다.
(만약 이것이 틀렸다면, 저에게 말해주세요.저는 이것에 대해 아무런 문제가 없었지만, 전문가는 아닙니다.)
여기 제안이 있습니다.
모델 컬렉션의 최대값을 유지할 별도의 컬렉션 만들기
const autoIncrementSchema = new Schema({
name: String,
seq: { type: Number, default: 0 }
});
const AutoIncrement = mongoose.model('AutoIncrement', autoIncrementSchema);
이제 필요한 각 스키마에 대해pre-save hook
.
를 들어, 이름이 " " " ", " " 이라고 합니다.Test
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
입니다.atomic
두 모두 동일한 작업, 두업이동일게반하않환습다를 .seq
값. 따라서 각 삽입은 동시 삽입 수에 관계없이 증분 seq를 얻습니다.또한 이것은 더 복잡한 자동 증분 로직으로 확장될 수 있으며 자동 증분 시퀀스는 숫자 유형으로 제한되지 않습니다.
테스트된 코드가 아닙니다.다음을 위한 플러그인을 만들 때까지 사용하기 전에 테스트하십시오.mongoose
.
업데이트 이 플러그인에서 관련 접근 방식을 구현했습니다.
문서에 _id 필드(sort 등)가 이미 있는 경우에도 응답은 시퀀스를 증가시키는 것 같습니다.이는 기존 문서를 업데이트하기 위해 '저장'하는 경우에 해당됩니다.아니야?
제 말이 맞다면, 당신은 다음으로 전화하고 싶을 거예요._id!== 0
몽구스 의사들은 이것에 대해 아주 명확하지 않습니다.내부적으로 업데이트 유형 쿼리를 수행하는 경우 pre('save')를 호출하지 않을 수 있습니다.
명확화
업데이트 시 '저장' 사전 방법이 실제로 호출된 것 같습니다.
불필요하게 시퀀스를 증가시키고 싶지 않다고 생각합니다.쿼리 비용이 많이 들고 시퀀스 번호가 낭비됩니다.
Schema의 필드 throughput()에 값을 할당할 때 Mongoose Document를 사용하는 데 문제가 있었습니다. 그count
개체 자체를 반환하고 해당 속성에 액세스해야 합니다.
저는 @Tigran의 답변에 따라 연주했고 다음은 제 출력입니다.
// My goal is to auto increment the internalId field
export interface EntityDocument extends mongoose.Document {
internalId: number
}
entitySchema.pre<EntityDocument>('save', async function() {
if(!this.isNew) return;
const count = await counter.findByIdAndUpdate(
{_id: 'entityId'},
{$inc: {seq: 1}},
{new: true, upsert: true}
);
// Since count is returning an array
// I used get() to access its child
this.internalId = Number(count.get('seq'))
});
버전: mongoose@5.11.10
스키마에 고유 필드가 있을 때는 위의 답변이 작동하지 않습니다. DB 수준 및 증분에서 고유 검사가 DB 수준 유효성 검사 전에 발생하기 때문에 위의 솔루션과 같은 자동 증분에서 많은 숫자를 건너뛸 수 있습니다.
사후 저장에서만 데이터가 이미 DB에 저장되었거나 오류가 반환된 경우 찾을 수 있습니다.
schmea.post('save', function(error, doc, next) {
if (error.name === 'MongoError' && error.code === 11000) {
next(new Error('email must be unique'));
} else {
next(error);
}
});
https://stackoverflow.com/a/41479297/10038067
그렇기 때문에 위의 답변 중 어떤 것도 dbs와 같은 sql의 원자적 작업 자동 증분과 같지 않습니다.
저는 @cluny85와 @edtech를 함께 사용합니다.하지만 저는 이 문제를 끝내지 못했습니다.
counterModel.findByIdAndUpdate({_id: 'aid'}, {$inc: { seq: 1} }, function(error,counter){
그러나 "pre('save...)" 함수에서 문서 저장 후 업데이트 카운터 완료의 응답입니다.그래서 나는 카운터 투 문서를 업데이트하지 않습니다.
모든 답변을 다시 확인해주시기 바랍니다.감사해요.
죄송합니다. 댓글을 추가할 수 없습니다.왜냐하면 저는 신입이기 때문입니다.
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();
}
});
언급URL : https://stackoverflow.com/questions/28357965/mongoose-auto-increment
'programing' 카테고리의 다른 글
vb.net 에서 메서드 이름 뒤에 있는 달러 기호의 의미는 무엇입니까? (0) | 2023.05.18 |
---|---|
Visual Studio가 "솔루션을 닫기 전에 빌드를 중지해야 합니다" 상태로 고착됨 (0) | 2023.05.18 |
git 저장소에서 암호를 처리하는 가장 좋은 방법은 무엇입니까? (0) | 2023.05.18 |
브라우저가 asp.net 응용 프로그램에서 최신 js 및 css 파일을 가져오도록 합니다. (0) | 2023.05.18 |
충돌하는 Gitrebase의 중간에서 "그들의" 변화를 얻는 방법은 무엇입니까? (0) | 2023.05.18 |