SequelizeJS: How to know success or failure when executing an INSERT raw query? - postgresql

I use PosgreSQL. Now I have an INSERT raw query. I want to know ask 2 questions:
I want to know if it is success or failure when executing it
If success, I want to get the new data I inserted
var querydb = INSERT INTO chat_message VALUES (DEFAULT, '${text}',
'${created_at}', '${room_id}', '${user_id}');
sequelize.query(querydb, { type: sequelize.QueryTypes.INSERT})
.then(insertID => {
resolve(insertID)
})
.catch(err => {
reject(err)
})

First of all you shouldn't be using raw queries until unless you are not able to do anything with sequelize.js , or else there is no use of using this library.
Use sequelize.js as much as possible , so that you can use default functionality very easily.
So this is how you can do the same thing in sequelize.js way :
ChatMessage.create({
text: text,
room_id: room_id,
user_id: user_id
created_at: new Date() // Not required , it will be auto managed by sequlize
}).then(message => {
console.log(message);
// you can now access the newly ChatMessage task via the variable message
}).catch(err => {
// catch error if anything goes wrong
})

Related

RTK Query correct way to map props with transformResponse

I'm working on linking up a scheduler component with data that I am receiving through an RTK Query api call. In order for the scheduler to work, I have to adjust the prop names to names the scheduler utilizes, before the state is available in the component (otherwise it does not load when I've tried in the React component). There is not a clear example of this being done in the RTK Query docs (https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#customizing-query-responses-with-transformresponse) , but it seems like it should be possible. When I've implemented it, the query gets fulfilled, but comes back as an empty object, or an array with a single empty object depending on how I've tried to structure it.
getUserScheduleVisits: builder.query({
query: userId => `/visitapi/visits/users/${userId}`,
providesTags: ['Visit', 'User'],
transformResponse: (response) => {
return {
data: [{
id: response._id,
startDate: response.visitStart,
endDate: response.visitEnd,
title: response?.client?.fullName
}]
}
},
}),
When I've run the query without the transform response, the data comes through as expected, however remains unusable by the Scheduler component I'm trying to implement. I'm still learning the complexities to RTK Query so I'm sure its how I'm trying to use transformResponse, I'm just not sure how to approach it correctly.
This would end up as result.data.data if you do const result = useMyQuery().
Did you maybe mean to do this?
getUserScheduleVisits: builder.query({
query: userId => `/visitapi/visits/users/${userId}`,
providesTags: ['Visit', 'User'],
transformResponse: (response) => {
return [{
id: response._id,
startDate: response.visitStart,
endDate: response.visitEnd,
title: response?.client?.fullName
}]
},
}),

Insert into relationship table using id created at user registration

I have two tables as seen below
The first table is for users and is populated via a registration form on the client side. When a new user is created, I need the second 'quotas' table to be populated with date, amount, and linked with the user id. The 'user_id' is used to pull the quotas information in a GET and display client side. I am having issues using the 'id' to populate the second table at the time of creation. I am using knex to make all queries. Would I be using join to link them in knex?
server
hydrateRouter // get all users
.route('/api/user')
.get((req, res) => {
knexInstance
.select('*')
.from('hydrate_users')
.then(results => {
res.json(results)
})
})
.post(jsonParser, (req, res, next) => { // register new users
const { username, glasses } = req.body;
const password = bcrypt.hashSync(req.body.password, 8);
const newUser = { username, password, glasses };
knexInstance
.insert(newUser)
.into('hydrate_users')
.then(user => {
res.status(201).json(user);
})
.catch(next);
})
client
export default class Register extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
glasses: 0
}
}
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost:8000/api/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.state)
})
.then(response => response.json())
.then(responseJSON => {
this.props.history.push('/login');
})
}
server side route for displaying the water amount
hydrateRouter
.route('/api/user/waterconsumed/:user_id') // display water consumed/day
.all(requireAuth)
.get((req, res, next) => {
const {user_id} = req.params;
knexInstance
.from('hydrate_quotas')
.select('amount')
.where('user_id', user_id)
.first()
.then(water => {
res.json(water)
})
.catch(next)
})
Thank you!
Getting the id of an inserted row
So this is a common pattern in relational databases, where you can't create the egg until you have the unique id of the chicken that lays it! Clearly, the database needs to tell you how it wants to refer to the chicken.
In Postgres, you can simply use Knex's .returning function to make it explicit that you want the new row's id column returned to you after a successful insert. That'll make the first part of your query look like this:
knexInstance
.insert(newUser)
.into('users')
.returning('id')
Note: not all databases support this in the same way. In particular, if you happen to be developing locally using SQLite, it will return the number of rows affected by the query, not the id, since SQLite doesn't support SQL's RETURNING. Best is just to develop locally using Postgres to avoid nasty surprises.
Ok, so we know which chicken we're after. Now we need to make sure we've waited for the right id, then go ahead and use it:
.then(([ userId ]) => knexInstance
.insert({ user_id: userId,
date: knex.fn.now(),
amount: userConstants.INITIAL_QUOTA_AMOUNT })
.into('quotas')
)
Or however you choose to populate that second table.
Note: DATE is a SQL keyword. For that reason, it doesn't make a great column name. How about created or updated instead?
Responding with sensible data
So that's basic "I have the ID, let's insert to another table" strategy. However, you actually want to be able to respond with the user that was created... this seems like sensible API behaviour for a 201 response.
What you don't want to do is respond with the entire user record from the database, which will expose the password hash (as you're doing in your first code block from your question). Ideally, you'd probably like to respond with some UI-friendly combination of both tables.
Luckily, .returning also accepts an array argument. This allows us to pass a list of columns we'd like to respond with, reducing the risk of accidentally exposing something to the API surface that we'd rather not transmit.
const userColumns = [ 'id', 'username', 'glasses' ]
const quotaColumns = [ 'amount' ]
knexInstance
.insert(newUser)
.into('users')
.returning(userColumns)
.then(([ user]) => knexInstance
.insert({
user_id: user.id,
date: knex.fn.now(),
amount: userConstants.INITIAL_QUOTA_AMOUNT
})
.into('quotas')
.returning(quotaColumns)
.then(([ quota ]) => res.status(201)
.json({
...user,
...quota
})
)
)
Async/await for readability
These days, I'd probably avoid a promise chain like that in favour of the syntactic sugar that await provides us.
try {
const [ user ] = await knexInstance
.insert(newUser)
.into('users')
.returning(userColumns)
const [ quota ] = await knexInstance
.insert({
user_id: userId,
date: knex.fn.now(),
amount: userConstants.INITIAL_QUOTA_AMOUNT
})
.into('quotas')
.returning(quotaColumns)
res
.status(201)
.json({
...user,
...quota
})
} catch (e) {
next(Error("Something went wrong while inserting a user!"))
}
A note on transactions
There are a few assumptions here, but one big one: we assume that both inserts will be successful. Sure, we provide some error handling, but there's still the possibility that the first insert will succeed, and the second fail or time out for some reason.
Typically, we'd do multiple insertions in a transaction block. Here's how Knex handles this:
try {
const userResponse = await knexInstance.transaction(async tx => {
const [ user ] = await tx.insert(...)
const [ quota ] = await tx.insert(...)
return {
...user,
...quota
}
})
res
.status(201)
.json(userResponse)
} catch (e) {
next(Error('...'))
}
This is good general practice for multiple inserts that depend on each other, since it sets up an "all or nothing" approach: if something fails, the database will go back to its previous state.

How to split up Postgres data into JSON/object, or an easily usable format for Express

I'm using pg-promise to facilitate requests between Express and a Postgres database.
Using pg-promise's any:
db.any('select * from blog')
.then(function (data) {
console.log(data);
})
.catch(function (error) {
console.log('ERROR:', error);
});
There is only one row in the Postgres table, so the query above gets a block of data from Postgres that, when output to the terminal, looks like this:
[ { id: 1,
date: '2018-12-17',
title: 'Here is a Title',
article: "Okay, there's not much here yet.",
img1: null,
img2: null,
img3: null,
keywords: 'news' } ]
In an effort to break up this data into usable bits that I can then assign to values in Express, I attempted to use JSON.parse() on this data. I really didn't know what to expect from doing this.
db.any('select * from blog')
.then(function (data) {
data = JSON.parse(data); // attempting to parse the Postgres data
console.log(data);
})
An error occurred:
ERROR: SyntaxError: Unexpected token o in JSON at position 1
I also tried to call on this data as if it were an object.
db.any('select * from blog')
.then(function (data) {
console.log(data);
console.log(data.id); // attempting to get just the id from the data
})
Which output to the terminal as:
undefined
How can I use this data within a js environment like Express? Not sure if it makes a difference, but I'm trying to use Pug to template everything to the front-end.
The select query returns array of objects with each element in the array corresponding to a row in the table (blog) in your case and each key in the object corresponding to the table column.
I am not sure why you are trying to JSON-parse it, as JSON expects an object, and it cannot parse arrays.
Try JSON.parse(JSON.stringify(data));

Massive Insert from a JSON file using Pg-Promise

Load huge JSON file using Pg-Promise helpers and fs stream.
I'm using pg-promise and I want to make massive inserts into a table using pgp.helpers. I've seen solution like Multi-row insert with pg-promise and also followed Data import for streams (Spex) but still it fails with the same error as in this post https://github.com/vitaly-t/spex/issues/8
I tried using a example from the other post on CSV stream(rs.csv()) but when i replaced the same with JSonStream parser I still get the same error.
Can you please share a working example?
db.tx(t => {
return streamRead.call(t, stream.pipe(parser), receiver)
})
There might be a better way to do it, but the below code sure works!
I have the chunks(row.length) at 20,000 per insert statement you can adjust accordingly based on your needs.
stream.pipe(parser)
parser.on('data', data =>{
row.push(data)
if (row.length === 20000) {
parser.pause()
//console.log(row.length)
db.tx('inserting-products', t => {
const insert = pgp.helpers.insert(row, cs)
t.none(insert).then(() => {
row =[]
parser.resume()
})
})
}
})
parser.on('end', () =>{
//console.log(row.length)
if(row.length != 0){
db.tx('inserting-products', t => {
const insert = pgp.helpers.insert(row, cs)
t.none(insert).then(() => {
console.log('success')
db.$pool.end()
})
})
}
if(row.length === 0) {
console.log('success')
db.$pool.end()
}
})
Please let me know in comments if this helps or any other ways to improve the process.

In mongo how to get the current position of the record in the table with the total records for pagination?

I'm trying to return create a paginated list. I used graphql to query the data. With my query, I pass the number of records I need (In a variable named first) and the ID of the last fetched record (In a varible called after). Now I managed to write a query (Note that I used mongoose) to fetch the records. Now what I need to do is get the relavant information to perform the pagination like hasNextPage, hasPreviousPage, currentPage and totalPages.
To get most of these information I need to get the total number of records in the database. To do that I need to send another db request.
I also need to know the position of the record in the table. No idea how.
Here's the query:
new Promise((resolve, reject) =>
Company.where('_id')
.gt(after)
.limit(first)
.lean()
.exec((error, doc) => {
if (error) {
reject(error);
}
resolve({
edges: doc,
pageInfo: {
hasNextPage: '...',
hasPreviousPage: '...',
currentPage: '...',
totalPages: '...'
}
});
}))
Any idea how to do this efficiently?
you can try this module mongoose-paginate
here what i uses, for pagination,
var current = req.query.filter.current;
var limit = req.query.filter.limit;
console.log('params.query.filter.current',current);
var skip = Number(limit)*Number(current)-Number(limit);
console.log('skip::',skip);
Cours.find({'attributes.version.status': true}).skip(skip).limit(limit).sort({_id:'asc'}).exec(function (err, resulta) {
if (err) {
console.log('erreur trouverCours');
res.json({
protecteds: err
});
}
console.log('cours ::', resulta);
res.json({
"data": resulta
});
});