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 |