Nodejs mongoose如何自定义ID(类似SQLSERVER) id自增长
Nodejs mongoose如何自定义ID(类似SQLSERVER) id自增长
才接触NODEJS的noder一枚 用mongodb的时候那个自己生成的ID太长 感觉不怎么好使 我想知道能办法自增长么? 1.2.3.4.5.6.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();
})();
解释
- AutoIncrementSchema:定义了一个用于存储自增 ID 的模型。每次插入新文档时,都会更新
currentId
字段。 - ActualDataSchema:定义了实际的数据模型,并在保存之前通过预处理函数(
pre('save')
)自动递增 ID。 - 使用示例:展示了如何连接到数据库并插入新的数据记录。
这种方法虽然简单,但需要注意并发问题,因为多个请求同时尝试获取下一个 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功能,可以通过自定义一个计数器来实现。
下面是一个简单的实现步骤和示例代码:
步骤
- 创建一个集合(例如
Counter
)来存储当前的自增ID。 - 在插入新文档时,先从
Counter
集合中获取当前的自增ID,然后递增该ID。 - 使用获取到的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的问题。