Nodejs mongoose如何自定义ID(类似SQLSERVER) id自增长

Nodejs mongoose如何自定义ID(类似SQLSERVER) id自增长

才接触NODEJS的noder一枚 用mongodb的时候那个自己生成的ID太长 感觉不怎么好使 我想知道能办法自增长么? 1.2.3.4.5.6.7…这样 开始想了个才学编程的一个方法 感觉不靠谱 不科学 所以求各位大大解答 百度谷歌很久没找到自己想要的

7 回复

当然可以!如果你希望在使用 Mongoose 和 MongoDB 时实现类似于 SQL Server 的自增 ID 功能,可以通过创建一个中间表来存储当前的最大值,并在插入新文档时递增这个值。以下是一个简单的示例来展示如何实现这一功能。

示例代码

首先,我们需要创建两个模型:一个是用于存储自增 ID 的模型,另一个是你需要操作的实际数据模型。

1. 创建自增 ID 模型

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 自增 ID 模型
const AutoIncrementSchema = new Schema({
    modelName: { type: String, required: true, unique: true },
    currentId: { type: Number, default: 0 }
});

const AutoIncrementModel = mongoose.model('AutoIncrement', AutoIncrementSchema);

2. 创建实际数据模型

const ActualDataSchema = new Schema({
    id: { type: Number, unique: true },
    name: { type: String, required: true }
});

ActualDataSchema.pre('save', async function (next) {
    if (!this.id) {
        const autoIncrementModel = await AutoIncrementModel.findOneAndUpdate(
            { modelName: 'YourModelName' }, // 这里的名字要与实际数据模型名称匹配
            { $inc: { currentId: 1 } },
            { new: true, upsert: true }
        );
        this.id = autoIncrementModel.currentId;
    }
    next();
});

const ActualDataModel = mongoose.model('ActualData', ActualDataSchema);

使用示例

(async () => {
    await mongoose.connect('mongodb://localhost:27017/yourdb', {
        useNewUrlParser: true,
        useUnifiedTopology: true
    });

    // 插入一条记录
    const newData = new ActualDataModel({ name: 'Test Data' });
    await newData.save();

    console.log(newData);

    // 查询所有记录
    const allData = await ActualDataModel.find({});
    console.log(allData);

    mongoose.disconnect();
})();

解释

  1. AutoIncrementSchema:定义了一个用于存储自增 ID 的模型。每次插入新文档时,都会更新 currentId 字段。
  2. ActualDataSchema:定义了实际的数据模型,并在保存之前通过预处理函数(pre('save'))自动递增 ID。
  3. 使用示例:展示了如何连接到数据库并插入新的数据记录。

这种方法虽然简单,但需要注意并发问题,因为多个请求同时尝试获取下一个 ID 时可能会导致冲突。如果需要更高的并发性能,可以考虑使用 MongoDB 的 findAndModify 方法或其他更复杂的设计模式。


我查询了一些人写的如何实现自增长ID ~ 都是跟我最开始的想法一样 ~ 添加数据的时候 去查一次获得最大ID 再加1 但是如果是高并发 多条数据同时查询的时候 获得的最大ID都是一样的 并都加1 最后导致的结果ID重复 求解…

mango不适合做这样的操作

人工置顶 = = ~ 求解丫 各位大大

mongoose official document already mention about this. You can choose a plugin of mongoose, http://plugins.mongoosejs.com/

官方给出一个方案,是使用findAndmodify,不知道会不会产生重复的ID。

function getNextSequence(name) {
   var ret = db.counters.findAndModify(
          {
            query: { _id: name },
            update: { $inc: { seq: 1 } },
            new: true
          }
   );

return ret.seq; }

http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/

在MongoDB中,Mongoose默认会为每个文档生成一个唯一的_id字段,通常使用的是ObjectId类型。不过,如果你希望实现类似于SQL Server中的自增ID功能,可以通过自定义一个计数器来实现。

下面是一个简单的实现步骤和示例代码:

步骤

  1. 创建一个集合(例如Counter)来存储当前的自增ID。
  2. 在插入新文档时,先从Counter集合中获取当前的自增ID,然后递增该ID。
  3. 使用获取到的ID作为新文档的ID。

示例代码

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 定义计数器模型
const counterSchema = new Schema({
    _id: { type: String, required: true },
    seq: { type: Number, default: 0 }
});

const Counter = mongoose.model('Counter', counterSchema);

// 定义主模型
const myModelSchema = new Schema({
    name: { type: String, required: true }
});

myModelSchema.pre('save', async function (next) {
    if (!this.isNew) return next();
    
    const modelName = this.modelName;
    let counter = await Counter.findOneAndUpdate(
        { _id: modelName },
        { $inc: { seq: 1 } },
        { new: true, upsert: true }
    );
    
    this._id = counter.seq;
    next();
});

const MyModel = mongoose.model('MyModel', myModelSchema);

// 连接到MongoDB
mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true, useUnifiedTopology: true });

// 插入示例数据
async function run() {
    const doc1 = new MyModel({ name: 'Document 1' });
    await doc1.save();
    console.log(doc1._id); // 输出: 1

    const doc2 = new MyModel({ name: 'Document 2' });
    await doc2.save();
    console.log(doc2._id); // 输出: 2
}

run().catch(err => console.error(err));

解释

  • Counter集合用于存储每个模型的当前自增ID。
  • pre('save')钩子确保每次保存新文档前,都会更新计数器并设置新文档的ID。
  • 使用findOneAndUpdate来原子性地更新计数器并返回更新后的值。
  • 这样,每个文档都有一个连续的自增ID,类似于SQL Server的行为。

这种方法虽然可以实现ID自增的需求,但需要注意的是,它可能不是最高效的解决方案,特别是在高并发环境下。此外,如果需要分布式部署,还需要考虑全局唯一ID的问题。

回到顶部