how to pass parameters from RTK to Node (mysql connection) - mysql

I've been trying for hours and I can't get it to work 100% correctly.
I've using RTK Query with a backend connection to a mysql server.
The issue is that I get all result and not from a specific query, no matter what param I use.
Let me explain:
in the backend (connection is working perfectly) part I have:
app.get("/test", (req, res) => {
const q = 'select * from portfolios'
db.query(q, (err, data) => {
if(err) {return res.json(err)}
return res.json(data)
})
})
in the API-part, I have:
const testerApi = createApi({
reducerPath: 'tester',
baseQuery: fetchBaseQuery({
baseUrl: "http://localhost:8800"
}),
endpoints(builder) {
return {
fetchTesting: builder.query({
query: (name) => {
return {
url: '/test',
params: {
user_id: name.id
},
method: 'GET',
};
},
}),
};
},
});
To call this, I use:
const name = {id:6, na:'iets'};
const results = useFetchTestingQuery(name);
but as a result, I get all content from the mysql test-table, it doesnt filter out the user-id.
So, the result always is something like this:
0
:
{id: 1, user_id: 1, name: 'aaaaaa'}
1
:
{id: 2, user_id: 1, name: 'bbbb'}
2
:
{id: 3, user_id: 2, name: 'cccc'}
3
:
{id: 9, user_id: 3, name: 'dddddd'}
...
So, it is partially working, but how can I get a filtered result?
This might sound a stupid question, but I am a beginner and I've been searching for hours to find a working solution.
I hope someone can help me a little bit ...
Thx,
Peter
tried many things, such as changing the bacnekd side to
app.get("/test/:user_id")
const q = 'select * from portfolios where user_id = ?'
db.query(q, [user_id], (err, data) => {...
and many more but nothing seems to work.

Related

Sequelize ORM - excluding Left Join

I'm building Full Stack, Social media app using Sequelize ORM.
sequelize: 6.6.5
sequelize-cli: 6.2.0
My database is built of tables Users, Posts and ReadPosts - which has two foreign keys - UserId and PostId.
One of the features of the app, is that user can easily see new posts, that have not been read by him/her yet, so every time user reads a post it generates a row in ReadPost table, made of UserId (who read the post) and PostId (which was read by the user).
What I'm trying to do now, is to display all posts that have not been read, so it would be some kind of excluding left join, that would get all existing posts, and exclude those pots from ReadPost with given userId, but I can't figure out how to do it with Sequlize.
ReadPost model:
module.exports = (sequelize) => {
const readPost = sequelize.define("ReadPost", {})
readPost.associate = models => {
readPost.belongsTo(models.User, {
foreignKey: {
allowNull: false
},
onDelete: "CASCADE",
foreignKeyConstrains: true
})
readPost.belongsTo(models.Post, {
foreignKey: {
allowNull: false
},
onDelete: "CASCADE",
foreignKeyConstrains: true
})
}
return readPost
}
I know I could do it virtually and just run findAll() on posts, and not display those that have not been read yet, depending on some javascript flag or simply class, but this is a project for my portfolio so I want to do it properly. Can I have some help please?
#Anatoly
I had to play a bit with your code, as I'm using newer version of sequelize and got something like this:
exports.showAllUnreadPosts = (req, res, next) => {
db.Post.findAll({
where: {
"ReadPost.id": null,
userId: res.locals.userId //userId extracted from authorization middleware
},
include: [{
model: db.ReadPost,
required: false,
attributes: []
}]
})
with that it retuns
"error": "Error SequelizeDatabaseError: Unknown column 'Post.ReadPost.id' in 'where clause'"
I tried to understand the line '"ReadPost.id": null', but as far as I understand sql syntax it would be looking for that column in Post table? I don't have such column, relation exists in ReadPost table, where it gathers userIds and postIds, not sure if my implementation is clear
Just in summary - I need to get all existing posts from Post table and compare it with ReadPost table, where postId and userId are stored. So probably I'd have to run findAll on Posts, findAll on ReadPost with current userId, and exclude all those postIds recorded in ReadPost from Post.findAll
Have a look screenshoot of how currently data looks like in those tables:
picture of DB tables
So baisically I need Post.findAll() + ReadPost.findAll() where userId: res.locals.userId and return all posts from Post table but do not exist with that ReadPost query.
I hope that makes it more clear.
#Anatoly 11/03/22
Query works now, but returns only posts that have not been read by ANY user (row doesn't exist) and the user is the author of the post.
What I managed to do for now, is get all posts that have been read by the user (code below). I need exact opposite of it (row doesn't exist or it exists, but not with this userId)
So, from all posts that exist, Select those read by user, and exclude those else from all of the posts in the DB
exports.showAllUnreadPosts = (req, res, next) => {
db.Post.findAll({
where: {
'$readposts.UserId$': res.locals.userId // User Id extracted from auth middleware
},
include: [{
model: db.ReadPost,
required: false,
attributes: [],
}]
}).then(unreadPosts => {
res.status(200).json(unreadPosts);
})
.catch((error) => {
res.status(500).json({
error: 'Error ' + error
})
})
}
Can you please advise?
Right, it seems like I found solution with a great help from #Anatoly.
I'm not sure, if it's a good idea, since I added a second method in the THEN block, I'm happy to get any feedback on it.
exports.showAllUnreadPosts = (req, res, next) => {
db.Post.findAll({
where: {
'$readposts.UserId$': res.locals.userId // User Id extracted from auth middleware
},
attributes: ['id'],
include: [{
model: db.ReadPost,
required: false,
attributes: [],
}]
}).then(readPosts => {
db.Post.findAll({
where: {
id: {
[Op.not]: (() => readPosts.map(readPost => readPost.id))()
}
}
})
.then((unreadPosts) => {
res.status(200).json(unreadPosts);
})
.catch((error) => {
res.status(500).json({
error: 'Error' + error
})
})
})
.catch((error) => {
res.status(500).json({
error: 'Error ' + error
})
})
}
First of all, there is a method that checks all the posts that are already read by the user in readpost table and returns post ids. Secondly in the THEN block, it gets all the existing posts in the db, and excludes those with ids from above method (by [OP.not]). I hope it makes sense, not sure about performance.
You can query all posts that doesn't have a link record in ReadPost by adding a condition Readpost.id is null like this:
const unreadPosts = await Post.findAll({
where: {
'$ReadPost.id$': null,
userId: userId
},
include: [{
model: ReadPost,
required: false,
attributes: [],
where: {
UserId: userId
},
}]
})
And of course, you need to add an association from Post to ReadPost:
Post.hasMany(ReadPost, <some_options_here>);

findOneAndUpdate in mongoose (MERN)

A small bottleneck arose while developing a short tutorial:
I would like to be able to push this model:
const studentFatherSchema = new Schema ({
yam:{
type: String,
trim: true
},
emailmanagement: {
type: String,
trim: true
},
students: [{
name: {
type: String,
trim: true
}
}]
});
Would I first have to find the parent object with findById (req.params.studentFatherId) and then do the update, or can I do it all at once? I'm trying to do it all at once, but I can't, what do you recommend?
Note: I can update the name and emailmanagement fields without problems, but doing an update with the push does not add it to me, I am testing it with Postman and
I have something like this but it doesn't work!
exports.updateAddChild = async (req, res, next) => {
try {
const student = req.body;
const studentFather = await StudentFather.findOneAndUpdate (
{_id: req.params.studentFatherId},
{$ push: {students: student}},
);
} catch (error) {
console.log (error);
next ();
}
}
Thank you very much for your help!

Sequelize ordering bug in multi join

I have Users table, that related to many Stations and each user has relation with Info table, that contains fields firstName and lastName. I grab it like this:
const joinUserInfo: any = {
model: userInfoModel,
where: { deletedAt: null },
required: true,
};
const joinStations = {
model: stationModel,
required: true,
};
const notFormatedItems = await this.userRepository.findAll({
where: { role: 'user' },
include: [joinUserInfo, joinStations],
paranoid: false,
order,
});
Than I have a method to build order. It looks like this:
private createAdminsListOrdering(query) {
const validOrderingItems = [];
if (query.fullName) {
validOrderingItems.push(['info', 'lastName', query.fullName]);
validOrderingItems.push(['info', 'firstName', query.fullName]);
}
if (query.email) {
validOrderingItems.push(['email', query.email]);
}
if (query.station) {
validOrderingItems.push(['stations', 'name', query.station]);
}
return validOrderingItems.push(['createdAt', 'DESC']);
}
In cases with email or stations all works correct. But with info it say that didn't see and info column. When I remove stations from join like this:
const notFormatedItems = await this.userRepository.findAll({
where: { role: 'user' },
include: [joinUserInfo],
paranoid: false,
order,
});
My ordering by firstName and lastName working correct. What i do wrong? Thank you.
Users related with Stations as many-to-many:
#BelongsToMany(
() => stationModel,
() => userStationModel,
)
stations?: stationModel[];
The problem was in pagination... I use custom function to create pagination:
export const paginatedQuery = ({ page = 0, pageSize = 0 }) => {
if (!pageSize) {
return {};
}
const limit = pageSize;
const offset = page * pageSize;
return { offset, limit };
};
And full my request was:
const notFormatedItems = await this.userRepository.findAll({
where: { role: 'user' },
include: [joinUserInfo, joinStations],
paranoid: false,
order,
...paginatedQuery(query),
});
And, when I debug request with logging i notice, that my Info table is in subquery. Then I began to googling about subqueries in sequelize and found flag subQuery, that force to not use subqueries. After this my request works fine:
const notFormatedItems = await this.userRepository.findAll({
where: { role: 'user' },
include: [joinUserInfo, joinStations],
paranoid: false,
order,
...paginatedQuery(query),
subQuery: false,
});
Hope it will helps someone.

Sequelize: How to retrieve updated record after sequelize update query without using another query

` User.update({
role: 'user'
}, {
where: {
email: email
}
}).then(function(result) {
//Returned value: either [0] or [1] i.e. record is updated or not
});
`
This is sequelize update query where User is model (user's role is updated by email). Its working fine but I want that using update query, I will get user's data as well. Is it possible to get it without using another query ?
Nope, not possible without another query. This isn't a limitation of Sequelize, it's a limitation of SQL. Under the hood, sequelize needs to do:
update users set role = 'user' where email = 'test#example.com'
which will just update the rows, but will not retrieve any rows. Then, it needs to do a second:
select * from users where email = 'test#example.com'
to actually get the (now updated) rows.
If you are using postgresql then you can set returning true after where clause
where: { socketID: socket.id },
returning: true,
and and if you are using other db like mysql as in my case then you cant to it in a single hit you have to use anther query like below
async function PersonalDetail(req, res) {
var Email = req.body.email;
const user = await User.findOne({ where: { EmailAddress: Email, IsActive: true } });
if (user != null) {
user.UpdateDate = new Date();
user.EmplomentID = req.body.EmplomentID;
user.LivingID = req.body.LivingID;
user.LocationID = req.body.LocationID;
await user.save();
res.json({
IsSuccess: true,
message: 'User updated',
User: user
});
}
else {
res.json({
IsSuccess: true,
message: 'User Not updated',
User: ""
});
}
}

How to Query Friends Posts In Rest API for a specific Route

I am working in SailsJS and I am attempting to build a REST API back-end for my mobile app that allows for a Newsfeed path so that if I query JSON on the front-end I can get it all from www.website.com/user/id/Newsfeed. Where the Controller gets each user's friends and their posts and displays it in JSON chronologically on that route. I am coming from an objective-C background so bear with my newbie-ness.
config/routes.js
module.exports.routes = {
'/': {
view: 'homepage'
},
'get /user/:id/newsfeed': {
controller: 'UserController',
action: 'newsfeed'
}
};
Model/User.js
var User = module.exports = {
//User attributes
attributes: {
facebookId: 'string',
accessToken: 'string',
location: 'string',
email: 'string',
first_name: 'string',
last_name: 'string',
about: {
interests: 'string',
goals: 'strings',
headline: 'string',
birthday: 'date'
},
friends : {
type: 'json'
},
posts: {
collection: 'posts',
via: 'user'
},
picture: 'string'
}
};
controllers/UserControllers.js
module.exports = {
newsfeed: function(req, res) {
var userId = req.session.id.friends;
sails.log("Searching for user's friends: "+ userId);
User.find({ where: { userId: { equals: userId}}}).exec(function(err, records) {
if(records && records.length == 0) {
sails.log("No friends found for user:" + userId);
sails.log(err);
return res.json(404, "No Friends Found :'(, you'll have alot soon! You're too cool not to.");
} else {
var friendsPostsArray = [];
for (i = 0; i < records.length; i++) {
var friendsPosts =records[i].posts;
friendsPostsArray.push(friendsPosts);
}
var uniquePosts = friendsPostsArray.filter(function (item, i , ar) {
return ar.indexOf(item) === i;
});
uniquePosts.sort();
sails.log(uniquePosts);
sails.log("Returning" + records.length + "friends found for user:" + userId);
return res.json(200, {friends: records, posts: uniquePosts});
}
});
}
};
Seems as though you should be storing friends as a collection of Users in the model:
friends: {
collection: 'user',
via: 'id'
}
And in your controller, populate your query with their friends and posts like so:
newsfeed: function (req, res) {
var userId = req.param('id');
sails.log("Searching for user's friends: " + userId);
User.find({ userId: userId })
.populate('friends')
.populate('posts')
.exec(function (err, found) {
/* Now we have a list of friends, we can find their posts */
User.find({ userId: found.friends })
.populate('posts')
.exec(function (err, found) {
/* Process friends posts here */
});
});
}
EDIT: Added the code needed to populate friends posts too.
The answer turned out to be a combination of Frederick's answer and some tweeking by another friend.
newsfeed: function (req, res) {
var userId = (req.param('id'));
sails.log("Searching for user's friends: " + userId);
User.find({ id: userId })
.populate('friends')
.populate('posts')
.exec(function (err, found) {
if (err) return res.status(err).json(400);
res.json(200, {found});
});
}
But it's still not completely done because this just returns a friends list and the :id user's posts. I used param instead of session and changed the find() portion so I don't know if I can give Frederick the green check of glory but definitely has my upvote. Hope this helps any fellow low-level coders!