How to use Knex with Transactions to save into SQLITE3 - javascript

Hey everyone i have the following code that retrieves data from cloud, then i need to save it to a database. I did it using Knex to make a seed file, and also using a regular function, but i need to do it using transactions with Knex.
Here is what i did :
function addPatient(){
return knex.transaction((t) => {
return knex('patients').insert({
uid: patient.uid,
first_name: patient.first_name,
last_name: patient.last_name,
birth_date: patient.birth_date,
code: patient.code,
birthsex: patient.birthsex,
})
}).then(t.commit)
.catch(function(e) {
t.rollback();
throw e;
})
}
Although sometimes i replaced the json by a variable object that gets all the data.
And i imported knex as following :
const knex = require(path.join(__dirname, 'knexfile.js'));
What intrigues me is i get this error :
knex.transaction is not a function, can anyone please hint or help or point to me where i am wrong ?
Thank you

Related

Resource not found querying dynamodb

I am trying to access a DynamoDb table, but I keep getting a "Resource not found" error.
The table is defined as follows, note that the table is Active and the Region is Paris (eu-west-3)
The code I am using:
export class EncuestaComponent implements OnInit {
[...]
client: DynamoDBClient = new DynamoDBClient({
region : 'eu-west-3',
credentials: {
accessKeyId: '[REDACTED]',
secretAccessKey: '[REDACTED]'
}
});
[...]
onDbClick() {
const commandParams = {};
const input: BatchExecuteStatementInput = {
Statements: [
{Statement: "SELECT opciones FROM encuesta.encuesta WHERE id = 'user.1'"}
],
}
const command = new BatchExecuteStatementCommand(input);
this.client.send(command).
then(data => console.log(data.Responses![0].Error)).
catch(error => {console.log("Error"); console.log(error)});
}
And, in the console, it shows that the then method has been executed, but the message printed is {Code: 'ResourceNotFound', Message: 'Requested resource not found'}
What am I doing wrong?
In PartiQL for DynamoDB, when you do select * from something.else means that you want it to query an index named else on table named something. Either you need to do one of the following:
escape the .
surround the table name with quotes
create a new table with a different name
I am not in front of my computer or i would figure out which it is for you, but this is where I'd start.
Here is something that might be causing the problem.
Can you confirm that
the accessKey that you are using have permission to read from the DynamoDB table?
that the accessKey has not expired and can be used?
Here are a few things that can help you test out the functionality try adding the key in ~/.aws/credentials and running this command.
aws dynamodb scan --table-name encuesta.encuesta
and confirm that it is indeed showing up the table content and not getting an access denied error.

TypeORM AfterSave() triggers after creation but when queried, it returns NULL

I have an Entity called Trip. The structure is:
What I want is whenever a new trip is created, the room column should be populated with ${tripId}_${someRandomStringHere}. So for example, I just created a new trip using this body:
The response should be:
The newly created trip has the id of 15. So, the response has the room valued at 15_4gupvdo0ea408c25ia0qsbh because again: ${tripId}_${someRandomStringHere}.
This is working as expected whenever I POST the request and create the trip. BUT whenever I query all the trips created, the room property of each trip objects shows null!
Look at the /api/trips:
room property is NULL. So what the heck I dont understand what is happening.
My Trip Entity code is:
import { PrimaryGeneratedColumn, Column, CreateDateColumn,
UpdateDateColumn, Entity, Unique, ManyToOne, AfterInsert, JoinColumn, getConnection } from 'typeorm'
import { DriverEntity } from 'src/driver/driver.entity';
#Entity('trips')
export class TripEntity {
#PrimaryGeneratedColumn()
id: number
#Column()
destination: string
#Column('decimal')
destination_lat: number
#Column('decimal')
destination_long: number
#Column()
maxPassenger: number
#Column()
totalPassenger: number
#Column({ nullable: true })
room: string
#CreateDateColumn()
created_at: Date
#UpdateDateColumn()
updated_at: Date
// --------->HERE: The after insert
#AfterInsert()
async createSocketRoom(): Promise<void> {
const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
this.room = `${this.id}_${randomString}`
}
// Trip belongs to driver
// Adds driver_id to trips table
#ManyToOne(type => DriverEntity, driver => driver.trips)
#JoinColumn({ name: 'driver_id' })
driver: DriverEntity
}
My Trip Service Code is:
async create(data: CreateTripDTO) {
const { driver_id } = data
const driver = await this.driverRepository.findOne({ where: { id: driver_id } })
const trip = await this.tripRepository.create(data)
trip.driver = driver
await this.tripRepository.save(trip)
return trip
}
I dont think I need to include the Trip Controller code but anyway..
I don't know why it is happening because I have my User Entity with #BeforeUpdate and works fine...
After reading alot of similar github issues, watched youtube tutorials [Hi Ben Awad! :D], I found a somewhat fix.. by using Subscribers
Actually, I don't know what is the difference of the Listener/Subscriber. Maybe I am doing the wrong usage. Can someone enlighten me please? For example the difference of AfterSave of Entity Listener vs AfterSave of Entity Subscriber. When/Best case to use? something like that. Anyway back with the "fix..."
I created a Trip Subscriber:
import { EventSubscriber, EntitySubscriberInterface, InsertEvent } from "typeorm";
import { TripEntity } from "src/trip/trip.entity";
#EventSubscriber()
export class TripSubsriber implements EntitySubscriberInterface<TripEntity> {
// Denotes that this subscriber only listens to Trip Entity
listenTo() {
return TripEntity
}
// Called after entity insertion
async afterInsert(event: InsertEvent<any>) {
console.log(`AFTER ENTITY INSERTED: `, event.entity);
const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
// query the trip with given event.entity
const trip = await event.manager.getRepository(TripEntity).findOne(event.entity.id)
// populate the room with desired format
trip.room = `${trip.id}_${randomString}`
// save it!
await event.manager.getRepository(TripEntity).save(trip)
}
}
At first it is not working but after digging for hours again, I need to add a subscriber property with the value of the path of my subscribers at the ormconfig.json for it to work!
e.g: "subscribers": [
"src/subscriber/*.ts"
]
Again, the Trip Subscriber code seems spaghetti to me because I already have the event.entity object but I do not know how to update it without the need of querying and updating it using event.manager.getRepository(). Please can someone fix this code for me? the proper way of doing it?
NOW, It is working!
the request body:
the /api/trips res:
My questions are:
Why whenever I use that method methoud subscriber, it is not working. Is it not the proper way to do it? The why is it in the docs? Or for other use case?
Do I really have to use subscriber for it to achieve? Thats so many steps.
I came from Rails. So having to create files/subscribers just to do it somewhat tiring. Unlike ActiveRecord's after_save callback it is very easy..
PS. I'm new to nest-js and typeorm
#AfterInsert method will just modify your JS object after inserting into DB is done. So thats reason why is your code not working. You have to use #BeforeInsert decorator. BeforeInsert will modify your JS entity/object before inserting/saving into DB.
What it looks like is happening with your AfterInsert is that you are creating the random room string just fine, but you are not saving the value to the database, only using the return of the id so that you can create the string. What you could do in your AfterInsert is run the save() function from the EntityManager or RepositoryManger once more and commit the value to the database, similar to what you have happening in you Subscriber. I haven't dived too deep into the Subscriber/Listener vs Before-/AfterInsert decorators, so I can't give a deeper answer to your questions.
If you'd rather not make two commits to the database, you can always do a query for the most recent id and increment it by 1 (thus, matching what the new objects id should be) with something like
const maxId = await this.tripRepository.findOne({select: ['id'], order: {id: "DESC"} });
const trip = await this.tripRepository.create(data);
const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
this.room = `${maxId + 1}_${randomString}`
trip.driver = driver
await this.tripRepository.save(trip)
It's a little clunky to look at, but it doesn't require two writes to the database (though you'll definitely need to ensure that after creation room and trip have the same id).
Your last option would be to create a Trigger in your database that does the same thing as your JavaScript code.
You just use "this.save()" after all in createSocketRoom() function
https://i.stack.imgur.com/oUY8n.png my query after use that!!!

get records after creation using sequelize raw query

I am using sequelize for migration. here I execute an INSERT query with following options but its didnot return created records:
const res = oldUsers.map(u => sequelize.query(
`INSERT INTO ${LP_LOCATIONS_TABLE} (name, address, city)
VALUES (
'${u.email}', '${u.address}', '${u.city}');`,
{ type: DataTypes.QueryTypes.INSERT, raw: true },
))
the output is an array of array like below:
[ [[0],[1]] ]
i expect to get created recorders. specially PK. how can I fix it?
I forgot to put RETURNING * at the end of the raw SQL query.
From the doc, you may have to specify the option returning:true to make this happen. I use mySql, so can't test (the returning option is only for postgres).

Mongoose how to see which mongodb query is being generated nothing returned from database

I'm currently using mongodb with mongoose.
When I connect to the database via the terminal and run the command:
db.locphoto.find({})
It successfully returns the list of items that I'm looking for.
Alternatively, on my application I do the following and unfortunately it constantly returns []. I was hoping someone could show me the way to see which mongodb query is generated so that I'm able to check if it is correctly generating db.locphoto.find({}).
My controller code is as follows:
var LocPhoto = require('../models/locPhoto');
module.exports.getGalleryPictures = function(req, res) {
LocPhoto.find({}, function(err, results) {
res.json(results);
});
}
And my model code is as follows:
var mongoose = require('mongoose');
var locPhotoSchema = mongoose.Schema({
challengeId: String,
image: String,
main: Number,
});
module.exports = mongoose.model('LocPhoto', locPhotoSchema);
I'd really appreciate if someone knows how to see the command that is being generated so that I can check this better in the future, since I've had this issue a few times already, it's usually to do with capital letters etc.
You're not properly creating the schema , you have to use new keyword
var locPhotoSchema = new mongoose.Schema({
challengeId: String,
image: String,
main: Number,
});

How do I post an HTML class into a mongoDB collection using express/mongoose and client-side JS?

First off my programming knowledge is entirely on the front-end, but I'm experimenting with node, express, mongoose, and mongodb. I'm using someone else's template to try and build an app the right way, but I'm lost when connecting the dots. I have the following jade:
form(method='post', action="/post/comment/" + post.id)
textarea(name='text')
input(type='submit', value='Save')
Combined with this from the routes/posts.js file
app.post("/post/comment/:id", loggedIn, function (req, res, next) {
var id = req.param('id');
var text = req.param('text');
var author = req.session.user;
Comment.create({
post: id
, text: text
, author: author
}, function (err, comment) {
if (err) return next(err);
res.redirect("/post/" + id);
});
});
and this is models/comment.js :
var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
var createdDate = require('../plugins/createdDate');
var schema = mongoose.Schema({
text: { type: String, trim: true, validate: validateText }
, post: { type: ObjectId, index: true }
, author: String
})
function validateText (str) {
return str.length < 250;
}
schema.plugin(createdDate);
module.exports = mongoose.model('Comment', schema);
Now this works fine, for submitting a comment and saving it in the DB. Problem is, is that I don't want to save a comment, but HTML after a function has manipulated it. So I tried:
var everything = $('.whatever').html();
$.post("/post/comment/:id", everything,
function(){
console.log('html saved!')
}
)
But I got a POST http://localhost:3000/post/comment/:id 500 (Internal Server Error) Now I'm aware that I probably don't have the id variable so I tried pasting in the number that is in the url, and that seemed to go through without error, but than didn't show up in the DB. I'm aware that this may not be a specific question, and that I may be going about this entirely wrong but any general direction would be much appreciated. Thanks.
You seem to have a number of problems here. Try taking a look at the following:
Your router is set to receive posts to "/post/comment/:id", but your post in the last code block is posting to "/post/comments/:id", where comments is plural. This will likely result in a 404. (Check the networks tab of your browser javascript console. It may be silently failing without you realizing it).
Your 500 error is likely coming from the fact that you directly posted ":id", instead of an actual identifier. Many node apps will have an app.param() block set up to validate these parameters, and your friend's template is likely breaking when it doesn't get a number it expects.
The data that you post must match the schema of the model you're saving it to. Any keys that aren't named in the schema will be stripped prior to saving, and in your case, if no keys match, it will just be a default comment instance, and won't save at all.
Hope that helps!

Categories

Resources