Javascript 猫鼬自增

Javascript 猫鼬自增,javascript,mongodb,mongoose,auto-increment,Javascript,Mongodb,Mongoose,Auto Increment,根据这是可能的自动递增一个字段,我想使用计数器收集方式 这个例子的问题是,我没有成千上万的人使用mongo控制台在数据库中键入数据。相反,我尝试使用猫鼬 因此,我的模式如下所示: var entitySchema = mongoose.Schema({ testvalue:{type:String,default:function getNextSequence() { console.log('what is this:',mongoose);//this is mongo

根据这是可能的自动递增一个字段,我想使用计数器收集方式

这个例子的问题是,我没有成千上万的人使用mongo控制台在数据库中键入数据。相反,我尝试使用猫鼬

因此,我的模式如下所示:

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;
      }
    }
});
我在同一个数据库中创建了counters集合,并添加了一个_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);

您只需初始化一次自动递增。

投票最多的答案不起作用。这是修复方法:

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;
    });
});
选项参数提供更新的结果,如果不存在,则会创建一个新文档。 你可以查看官方文件


如果您需要一个排序索引,请检查这个

,即使文档已经有一个_id字段(排序,无论什么),答案似乎也会增加顺序。如果“保存”以更新现有文档,则会出现这种情况。没有

如果我是对的,您会想调用next(),如果是这样的话。\u id!==0

猫鼬医生对此并不十分清楚。如果它在内部执行更新类型查询,则可能不会调用pre('save')

澄清

似乎在更新时确实调用了“save”pre方法

我认为你不想不必要地增加你的序列号。这会花费你一个查询,浪费序列号

注意! 正如和所指出的,如果删除文档,此将不起作用

如果插入3个id为
1
2
3
的文档,则删除
2
并插入另一个新文档,它将获得已使用的id为
3

如果您从未删除文档,请执行以下操作:

我知道这已经有了很多答案,但我想与大家分享我的解决方案,我的解决方案简短易懂:

// 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.\u id
具有
类型:Number

Mongoose版本:
5.0.1

我同时使用@cluny85和@edtech。 但是我没有完成这个问题


findByIdAndUpdate({u id:'aid'},{$inc:{seq:1}},函数(错误,计数器){
但在函数“pre('保存…)中,则更新计数器的响应在保存文档后完成。 所以我不更新文件的计数器

请再次核对所有答案。谢谢


抱歉。我不能添加评论。因为我是新手。

我不想使用任何插件(一个额外的依赖项,除了我在server.js中使用的插件之外,初始化mongodb连接等等),所以我做了一个额外的模块,我可以在任何模式下使用它,甚至,我正在考虑从数据库中删除文档的时候

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;
希望对你有帮助


(如果这是错误的,请告诉我。我对此没有任何问题,但不是专家)

因此,结合多个答案,这就是我最终使用的:

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;
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);
myModel.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;
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);

这个问题已经足够严重了,而且有足够多的问题,最好依靠一个经过测试的mongoose插件

在大量的“自动增量”插件中,维护和记录最好的(而不是fork)是。

这里有一个建议

创建单独的集合以保存模型集合的最大值

现在,对于每个需要的模式,添加一个
预保存钩子

例如,让集合名称为
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
是一个
原子的
操作,任何两次更新都不会返回相同的
seq
值。因此,无论并发插入的次数有多少,每次插入都会得到一个递增的seq。这也可以扩展到更复杂的自动递增逻辑,并且自动递增序列不受限制ed到数字类型

这不是经过测试的代码。请在使用之前进行测试,直到我为
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;
});
这种方法的好处之一是所有计数器相关逻辑都是独立的。您可以将其存储在单独的文件中,并将其用于导入
计数器模型的多个模型

如果要增加
\u id
字段,则应在架构中添加其定义:

const entitySchema = new mongoose.Schema({
    _id: {
        type: Number,
        alias: 'id',
        required: true,
    },
    <...>
});
const entitySchema=new mongoose.Schema({
_身份证:{
类型:数字,
别名:“id”,
要求:正确,
},
});

通过put()为架构的字段赋值时,我在使用Mongoose文档时遇到问题。
计数
返回一个对象本身,我必须访问它的属性

我按@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'))
});
//我的目标是自动递增internalId字段
导出接口EntityDocument扩展了mongoose.Document{
内部ID:编号
}
entitySchema.pre('save',异步函数(){
如果(!this.isNew)返回;
const count=wait counter.findByIdAndUpdate(
{u id:'entityId'},
{$inc:{seq:1}},
{new:true,upsert:true}
);
//因为count正在返回一个数组
//我使用get()访问它的子对象
this.internalId=Number(count.get('seq'))
});

版本:mongoose@5.11.10完美运行的解决方案

Mongodb自动增量字段

我有信用卡