Sequelize create make more than one record issue - javascript

I'm trying to save logs on some events with sequelize create but when I call the create method more than one record saved (maybe 2 or 3 identical records).
I'm using node.js and sequelize.
I made sure that I called add method once and I await it.
controller:
async addLog(){
let log = await UserLog.addLog({Uid:user_id,date:new Date()})
return log
}
UserLog model:
public static async addLog(logObject: LogType) {
return await LogEntity.create(logObject, {raw: true});
}
any suggestions

Make sure addLog() function is getting called from one point only.
You can use upsert function of sequileze which inserts a new record only if a unique condition doesn't meet else it will updates the record. In your case Uid and date can be used for uniqueness.

Related

Sequelize call thorws error in JEST test, how to make sequelize call in jest?

I want to test a controller which adds a record in the database, but I notice that even a select query throws an error, however when I add the record through my program, it is saved in the database.
For example only this query does not return anything but an error.
const facility = await db.facility.findOne({
where: { id: req.body.facility_id },
raw: true,
});
why does this query does not work in jest test file?
how can I solve this?
what is the best way to it?

Retrieve id of model created in $afterInsert hook in Objection ORM

Is it possible to retrieve (at least) the id of created model in $afterInsert hook in Objection ORM?
async $afterInsert(queryContext)
I guess and hope it could be available somehow from queryContext?
The goal is to be able to log this id when created in an allowed graph through insertGraph method.
You can access the returned data at this:
async $afterInsert(queryContext) {
await super.$afterInsert(queryContext);
console.log(this.id)
}

Access the request object from Express inside a Mongoose Plugin

I have an API in ExpressJS and a middleware that gets executed before each endpoint controller:
app.use(segregationMiddleware);
app.get('/some-endpoint', controller1);
app.get('/some-endpoint-2', controller2);
The segregationMiddleware is used to look for some parameters in the request and then it calculates a value that then is stored in the request object as req.locals.domain so the controllers can access it.
In each Mongoose model, I define a field named domain using a Mongoose plugin (so I don't have to do it every time). That field is used to segregate my assets. This means that when the segregationMiddleware populates req.locals.domain = 'foo' for example, if I make a model.find({}) I want to get only assets that have { domain: 'foo' }. Same thing if I try to update, save, delete, and so.
Of course, I can just simply modify the query on each controller since I have accesso to req, but I need to do it every time and I need to remember it for finds, findAndUpdate, save, and soo... sooner or later I'm gonna forget it.
I can define some hooks in Mongoose that will modify the query using a plugin so it adds the domain constraint to the query so I don't have to do it in the controller BUT I don't have the current req object in the Mongoose plugin unless I pass it, and the only way that come to my mind is to abstract the DB methods in the plugin, so in the controller, I do something like this:
model.safeFind(req, query);
And in the plugin I define safeFind like:
safeFind = () => {
const theRealQuery = Object.assign({}, query, { domain: req.locals.domain });
return this.find(query);
}
BUT, in this way, I need to redefine each DB query function (find, findOne, update, save...) and I need to remember to use the safe methods. Then again, I'm going to forget it sooner or later.
Is there a way I can still use the regular Mongoose methods from the controller and have the plugin somehow modify the query for every method using the current req object?

Create and run migrations in run time with Knex

I'm using strapi alongside knex, however strapi doesn't create any migrations and when you edit a content type (Model) by deleting a property or renaming it, it doesn't delete the targeted property, it just creates a new one, and when you delete a model it doesn't actually delete the table on the database.
This is really annoying because you'll end up with a lot of redundancies and unused tables and fields while developing.
What I'm doing is overriding the Strapi controllers that are responsible for creating, removing or updating a model and I want to be able to create a migration with the new schema on those controllers and then run it so I keep my database clean and up-to-date with strapi's models.
I know about the existence of knex.migrate.make however it doesn't seem to address my issue and the docs don't really tell you how to provide the migration fields to that function.
I was able to also find this http://knexjs.org/#custom-migration-sources however once again the docs are not very clear on what options I can provide and how to solve my issue.
Ideally I would want to end up with something like:
updateModel({attributes, table}){
const updatedSchena = attributes
knex.migrate.make(`update_${table.name}_table`, updatedSchema);
}
Edit:
I was able to create the new migration at run time but the contents of the file remain empty.
This is what I have so far
New custom-migration-sources as indicated in the docs:
class MyMigrationSource {
// Must return a Promise containing a list of migrations.
// Migrations can be whatever you want, they will be passed as
// arguments to getMigrationName and getMigration
constructor(name, attributes) {
this.name = name
this.attributes = attributes
console.log('attributes: ', attributes)
}
getMigrations() {
// In this example we are just returning migration names
return Promise.resolve(['migration1'])
}
getMigrationName(migration) {
return migration;
}
getMigration() {
return {
up(knex) {
//const migrate = require('widget-knex-schema')
return migrate.createTable(knex, this.name, this.attributes)
},
down(knex) {
return knex.schema.dropTableIfExists(this.name)
}
}
}
}
Instantiate the new migration source
const migration = new MyMigrationSource(modelJSON.collectionName, formatedAttributes)
Create the new migration with the custom configuration:
knex.migrate.make(`update_${name}_table`, {
migrationSource: migration
})
And the result is a new migration with these contents:
exports.up = function(knex) {
};
exports.down = function(knex) {
};
NOTE: I know that ´widget-knex-schema´is working because I use for other manually created migrations.
Can anyone link to any working examples or solutions on how to create migrations in run time?

Why do we need a new object in bookshelf.js fetch() method?

I'm new to Node and using bookshelf.js as the ORM for my current project. The documentation of bookshelf.js contains this snippet under fetch() method:
// select * from `books` where `ISBN-13` = '9780440180296'
new Book({'ISBN-13': '9780440180296'})
.fetch()
.then(function(model) {
// outputs 'Slaughterhouse Five'
console.log(model.get('title'));
});
http://bookshelfjs.org/#Model-fetch
What confuses me is why do we need to create a new object here if we are querying for an existing record? Does the way bookshelf.js works requires a new object to be created for every returned result?
This is confusing. At the moment there is only one type of object that represents both "model" and "query builder".
fetch prefills the WHERE clause with the set attributes on the model.
There are plans underway to change this. Discussion here.
Instead of writing your code as above, I'd recommend doing something like this:
// select * from `books` where `ISBN-13` = '9780440180296'
Book.where({'ISBN-13': '9780440180296'})
.fetch()
.then(function(model) {
// outputs 'Slaughterhouse Five'
console.log(model.get('title'));
});
(I realize you've just copied this straight from the docs.)
If you wish to update a model in place, prefer to use the new Model#refresh:
Book.forge({id: 5}).refresh().then(function (book) {//...

Categories

Resources