Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 526 Vote(s) - 3.43 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Mongoose auto increment

#11
I've combined all the (subjectively and objectively) good parts of the answers, and came up with this code:

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;
});

One of the benefits of this approach is that all the counter related logic is separate. You can store it in a separate file and use it for multiple models importing the `CounterModel`.

If you are going to increment the `_id` field, you should add its definition in your schema:

const entitySchema = new mongoose.Schema({
_id: {
type: Number,
alias: 'id',
required: true,
},
<...>
});
Reply

#12
This problem is sufficiently [complicated](

[To see links please register here]

) and there are enough [pitfalls](

[To see links please register here]

) that it's best to rely on a tested mongoose plugin.

Out of the plethora of "autoincrement" plugins at

[To see links please register here]

, the best maintained and documented (and not a fork) is [mongoose sequence](

[To see links please register here]

).
Reply

#13
> ## Attention!
As [hammerbot](

[To see links please register here]

) and [dan-dascalescu](

[To see links please register here]

) pointed out this **does not work** if you remove documents.

> If you insert 3 documents with id `1`, `2` and `3` - you remove `2` and insert another a new one it'll get `3` as id which is already used!


In case you don't ever remove documents, here you go:

I know this has already a lot of answers, but I would share my solution which is IMO short and easy understandable:

// 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();
}
});
Make sure that `entitySchema._id` has `type:Number`.
Mongoose version: `5.0.1`.
Reply

#14
I had an issue using Mongoose Document when assigning value to Schema's field through put(). The `count` returns an Object itself and I have to access it's property.

I played at @Tigran's answer and here's my output:

// 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'))
});

Version: [email protected]
Reply

#15


<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

test.pre("save",function(next){
if(this.isNew){
this.constructor.find({}).then((result) => {
console.log(result)
this.id = result.length + 1;
next();
});
}
})

<!-- end snippet -->

Reply

#16
None of above answer works when you have unique fields in your schema
because unique check at db level and increment happen before db level validation, so you may skip lots of numbers in auto increments like above solutions
only in post save can find if data already saved on db or return error


schmea.post('save', function(error, doc, next) {
if (error.name === 'MongoError' && error.code === 11000) {
next(new Error('email must be unique'));
} else {
next(error);
}
});

[To see links please register here]


that is why none of above answers are not like atomic operations auto increment in sql like dbs
Reply

#17
After reading the previous good answers, here is my concise solution in TS:

### counter.ts
```
import {Schema, model} from 'mongoose';

const counterSchema = new Schema({
_id: {
type: String,
required: true,
unique: true
},
seq: {
type: Number,
default: 0
}
});

const Counter = model('counter', counterSchema);

export async function getCounter(counterName: string): Promise<number> {
const count = await Counter.findByIdAndUpdate(
counterName,
{$inc: {seq: 1}},
{new: true, upsert: true}
);
return count.seq;
}
```

### test.ts
```
import {model, Schema} from 'mongoose';
import {getCounter} from "./counter";

const testSchema = new Schema(
{
seq: Number,
name: {
type: String,
required: true
}
});

testSchema.pre('save', async function (next) {
if (!this.isNew) return;
this.seq = await getCounter('test');
next();
})
export const Test = model('test', testSchema);
```

### index.ts
```
import {Test} from "./test";

const testObj = new Test({name: 'TEST'});
```
Reply

#18
without using any packages, you can just sort your primary id field by descending order and then increment it by one.

id field must be Number type

Model.find().sort({id: 'desc'}).limit(1).exec(function(err,model){
console.log(err,model);

//model is an array
const newId = ++model[0].id

console.log('new id: ',newId)

});


Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through