Need a sequelize alternative to a find raw query - node.js

SELECT * FROM recommended_plan WHERE user_id = ? AND created_at = (SELECT MAX(created_at) FROM recommended_plan WHERE user_id = ?)
I am stuck at converting this raw query into a sequelize one.

CASE 1 - you have only one record with max created_at value
First you can convert it to this equivalent one:
SELECT * FROM recommended_plan WHERE user_id = ?
order by created_at desc
limit 1
(Please pay attention that the limit option depends on a certain DBMS and could have a different name and/or syntax).
Now you can easily construct the corresponding Sequelize query:
const plan = await RecommendedPlan.findAll({
where: {
user_id: userId
},
limit: 1,
order: [['created_at', 'desc']]
})
CASE 2 - you have several records with max created_at value:
You can use Sequelize.literal to use a condition with a subquery:
const plan = await RecommendedPlan.findAll({
where: {
user_id: userId,
created_at: Sequelize.literal('(SELECT MAX(created_at) FROM recommended_plan rp WHERE rp.user_id = $userId)')
},
bind: {
userId: userId
}
})

Related

mongodb get collection.aggregate reponse sorted

i have a nodejs server with mongodb database and a collection with the following structure:
{user_id: int, country: string}
i need to get the country name that have the most users from.
currently what i do is get collection.distinct to get unique countries, and after that i run aggregate query to get the count and finally i sort the response_array manually to get the highest count, my question is what i need to add to the query in order to get the data sorted from the database so i wont need to sort it after the response?
let query = {};
for (let i = 0; i < countries.length; i++)
{
let country = countries[i];
query[country] = [{
$match: { country: country}
}, { $count: "count" }]
}
let response_cursor = await collection.aggregate([{$facet: query}]);
let response_array = await response_cursor.toArray();
//sorting the response_array

Implementing mongodb pagination along with match query?

I have user document as this
users = [
{
_id:'',
name:'jay',
email:'jay#gmail.com',
role: 'actor',
status: true // isActive
},
{
_id:'',
name:'ram',
email:'ram123#gmail.com',
role: 'electrician',
status: false // isActive
},
...... so on
]
I want to apply pagination and also some filters to retrieve data
filter = {
role: 'actor',
order: -1 //descending sort,
sortOn: 'name' // apply sort on name field
search: 'ja', // match the string starting with 'ja',
status: true,
size:25,
page: 1 // means documents from 1-25, page2 means 26-50
}
How can this be achieved?
I am using mongoose as well.
Using your filter object you can do something like this:
Use these steps to ensure a good pagination:
Sort by any value (to ensure not get random positions)
Skip by the number of pages
Limit by the number of elements into page
So, the query will be something like (not tested but you can see the idea):
const elementsPerPage = filter.size
const nSkip = elementsPerPage * filter.page
const sort = {[filter.sortOn]:filter.order}
YourModel.find({/*yourquery*/})
.limit(elementsPerPage)
.skip(nSkip)
.sort(sort)
Also, you can use filter values into your query, something like:
YourModel.find({
role: filter.role,
status:filter.status,
name:{ $regex: filter.search}
})
This query is like this example.
Also, is not defined what calues do you want to use, the condition etc, so, with this, you can use if/else to add or not values into query.
For example:
var query = {}
if(filter.search){
query.name = {$regex: filter.search}
}
So all together can be:
const elementsPerPage = filter.size
const nSkip = elementsPerPage * filter.page
const sort = {[filter.sortOn]:filter.order}
var query = {}
if(filter.search){
query.name = {$regex: filter.search}
}
if(filter.role){
query.role = filter.role
}
if(filter.status){
query.status = filter.status
}
YourModel.find(query)
.limit(elementsPerPage)
.skip(nSkip)
.sort(sort)
Note that this has not been tested, but as I've said before you can see the idea with this example.

Is there a way I can use Group By and Count with Type Orm Repository

I am new here recently joined and New in Type ORM My code that I am trying
FIRST QUERY: I would like to use this approach but not sure how I can group by with count on the column and then order by desc on that column
const result = await this.jobViewsRepository.find({
relations: ["jobs"],
loadEagerRelations: true,
order: { id: "DESC" },
skip: offset,
take: limit,
}
);
I am trying if I can use this in my above query
SECOND QUERY: IT'S WORKING FOR ME PERFECTLY THE RESULT I AM LOOKING
const res = await this.jobViewsRepository.createQueryBuilder('jobViews')
.addSelect("COUNT(jobViews.user_id) AS jobViews_total_count" )
.leftJoinAndSelect(Jobs, "jobs", "jobs.id = jobViews.job_id")
.where("jobs.user_id != :id", { id: user_id })
.groupBy("jobViews.job_id")**
.orderBy('jobViews_total_count', 'DESC')**
.limit(limit)
.offset(offset)
.getRawMany();
Please if any can help me out in this will be really appreciated
Thanks
At least in the current version there is no way to do this feature (neither in the documentation nor in the web)
I believe you can use .query to write your own query
Now is the only one way is to use queryBuilder And .groupBy("user.id") with .addGroupBy("user.id")
https://orkhan.gitbook.io/typeorm/docs/select-query-builder#adding-group-by-expression
Or write raw query:
import { getManager } from 'typeorm';
const entityManager = getManager();
const someQuery = await entityManager.query(`
SELECT
fw."X",
fw."Y",
ew.*
FROM "table1" as fw
JOIN "table2" as ew
ON fw."X" = $1 AND ew.id = fw."Y";
`, [param1]);
you use findAndCount to count the result size
result = await this.jobViewsRepository.findAndCount({ ... })
the result = [data,count]

get user's rank by points and registration date in sails.js

How to get the users rank using it's points and registration time ? i have tried to get users by same criteria and it's working fine.
await User.find({
sort: {
rewardPoints: 0,
createdAt: 1
}
}).limit(limit);
Now i want to get my rank only but it is not giving me correct result's by this code
await User.count({
createdAt: { "<" : user.createdAt },
rewardPoints: { ">=": user.rewardPoints },
});
i was finally did it using a sql query:
SELECT id
, firstName
, rank
FROM (
SELECT
*
, (#rank := #rank + 1) AS rank
FROM
user
CROSS JOIN(
SELECT
#rank := 0
)
AS
init_var_var
ORDER BY
user.rewardPoints DESC,
user.createdAt ASC
)
AS logins_ordered_ranked
WHERE
id = "${user.id}"

Sequelize raw query not properly printed

I am trying to write query in sequelize but query is not working below is my query that I write in sequelize
var homePosts = db.postbox.findAll({
where: {
user_id: {
$or: {
$eq: id,
$in: [id]
}
}
},
attributes: ["user_posts_id"],
limit: 5
});
return homePosts;
Node js print result query
Executing (default): SELECT `user_posts_id` FROM `user_posts_boxes` AS `user_posts_boxes` WHERE `user_posts_boxes`.`user_id` = '[object Object]' LIMIT 5;
[]
It prints object instead of variable value and print the actual query that sequelize prepare.
My actual raw query is following which I actually want to convert into sequelize
SELECT `user_posts_id` FROM `user_posts_boxes` AS `user_posts_boxes` WHERE ( `user_posts_boxes`.`user_id` = '5' OR `user_posts_boxes`.`user_id` IN (select following_id from friend WHERE friend.follower_id = user_posts_boxes.user_id and friend.status='A' and friend.following_id=5)) LIMIT 5
I had the same issue with Sequelize 5. Use Symbol based operator and it should be fine https://github.com/sequelize/sequelize/issues/8417

Resources