get user's rank by points and registration date in sails.js - node.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}"

Related

Need a sequelize alternative to a find raw query

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
}
})

Sequelize query with two JOINs on custom fields

Currently I've got a solution with the following raw query, which works well.
Here's a SqlFiddle playground.
And here's the raw query that works well:
const sql = `SELECT u.*, g.name AS "gender"
FROM users u
INNER JOIN connections con ON con.user_id = u.id
INNER JOIN completed_quizzes q ON q.user_id = u.id
LEFT JOIN genders g ON g.id = u.gender_id
WHERE
con.other_user_id='foo'
AND q.quiz_id=1
AND con.status='approved'
AND u.deleted_at IS NULL
AND con.deleted_at IS NULL
AND q.deleted_at IS NULL
LIMIT 10
OFFSET 0
`;
But I'm trying to replace it with Sequelize's object modelling. So far, the most meaningful solution I've come up with this:
const sequelize = {
include: [
{
model: ConnectionsModel,
as: 'connections',
where: { otherUserId: userId, status: ConnectionStatus.approved },
required: true,
duplicating: false
},
{
model: CompletedQuizzesModel,
as: 'completedQuizzes',
where: { userId, quizId },
required: true,
duplicating: false
},
{
model: GendersModel
}
],
nest: true,
// have to specify `raw: false`, otherwise Sequelize returns only the first associated record
raw: false
};
It generates the following query (I've prettified it, for ease of reading):
SELECT u.*, g.name AS gender FROM users AS u
INNER JOIN connections AS con ON u.id = con.user_id AND (con.status = 'approved' AND con.other_user_id = 'foo')
INNER JOIN completed_quizzes AS q ON u.id = q.user_id AND (q.user_id = 'foo' AND q.quiz_id = '1')
LEFT OUTER JOIN genders AS g ON u.gender_id = g.id
WHERE u.deleted_at IS NULL
LIMIT 20
OFFSET 0;
But it returns nothing... no rows. Whereas, the original solution returns the rows as needed.
I can see the difference between the general where (which is applied to the whole query in the raw query) and the same attributes appended to the on clause in the joins. Not sure if that's the problem, though.
Here's the SqlFiddle playground again.
You added an extra condition in the include option CompletedQuizzesModel. In the original SQL query you don't have a condition on userId.
So this include should be like this:
{
model: CompletedQuizzesModel,
as: 'completedQuizzes',
where: { quizId }, // removed userId
required: true,
duplicating: false
}
The result query works just like the original one:
SELECT u.*, g.name AS gender FROM users AS u
INNER JOIN connections AS con ON u.id = con.user_id AND (con.status = 'approved' AND con.other_user_id = 'foo')
INNER JOIN completed_quizzes AS q ON u.id = q.user_id AND (q.quiz_id = '1')
LEFT OUTER JOIN genders AS g ON u.gender_id = g.id
WHERE u.deleted_at IS NULL
LIMIT 20
OFFSET 0;

PostgreSQL query returning values that are not in my database

I am working on constructing a query to my database to return some data. Here is the link to a previous post describing my intentions Finding database data that best fits user variable responses. I want to return all of the columns for each data object, however the id that is returned is not correct and an additional VALUE field is being returned.
My database is set up like this
venues
id name parking decorations hotel
1 park 1 2 1
2 beach 1 2 2
3 theater 2 2 2
4 yard 2 1 1
and an enum table
id value
1 TRUE
2 FALSE
3 MAYBE
I am building a query on my backend as follows:
let searchConstraintsTrue = 'WHERE';
let firstItemTrue = 0;
for (const prop in req.body) {
if (req.body[prop] === 'TRUE') {
if (firstItemTrue === 0) {
searchConstraintsTrue += ` ${prop} = 1`;
firstItemTrue++;
} else {
searchConstraintsTrue += ` AND ${prop} = 1`;
}
}
}
let searchConstraintsMaybe = 'ORDER BY';
let firstItemMaybe = 0;
for (const prop in req.body) {
if (req.body[prop] === 'MAYBE') {
if (firstItemMaybe === 0) {
searchConstraintsMaybe += ` (${prop} = 1)::integer`;
firstItemMaybe++;
} else {
searchConstraintsMaybe += ` + (${prop} = 1)::integer`;
}
}
}
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
let sqlText = `SELECT * FROM venues
INNER JOIN response_enum rp ON rp.id = venues.parking
INNER JOIN response_enum rd ON rd.id = venues.decorations
INNER JOIN response_enum rh ON rh.id = venues.hotel
${searchConstraintsTrue} ${searchConstraintsMaybe} DESC`;
I realize that my searchConstraintsTrue and searchConstraintsMaybe are not properly using the enum table but right now I am just trying to get things working.
An example response looks like this:
[ {
id: 1,
name: 'beach',
parking: 1,
decorations: 2,
hotel: 1,
value: 'TRUE'
},
{
id: 2,
name: 'yard',
parking: 1,
decorations: 2,
hotel: 2,
value: 'FALSE'
}]
So I am returning the desired data however the id's are incorrect and there is a value column which doesn't exist in my database.
SELECT * will select all fields from the joined tables. You need to specify a list of fully qualified field names like so:
SELECT v.id,v.name,v.parking,v.decorations,v.hotel FROM venues v
INNER JOIN response_enum rp ON rp.id = venues.parking
INNER JOIN response_enum rd ON rd.id = venues.decorations
INNER JOIN response_enum rh ON rh.id = venues.hotel
${searchConstraintsTrue} ${searchConstraintsMaybe} DESC

How to get lastest inserted record _id in mongoose

I am trying to get recently inserted record _id and p_id but i do not know how to get the value.Below given my code.This is not working.How to do it?
DB records:
{
_id:5eba58f0e5def333ad4d8c8d,
p_id:"C1",
product_name:"Name",
product_weight:123
},
{
_id:5eba58f0e5def333ad4d8c8e,
p_id:"C2",
product_name:"Name",
product_weight:123
},
{
_id:5eba58f0e5def333ad4d8c8f,
p_id:"C3",
product_name:"Name",
product_weight:123
}
data.controller.js:
var Product = mongoose.model(collectionName);
let latest_id = Product.findOne().sort({ field: 'asc', _id: -1 }).limit(1);
console.log("_id" + val); //output should be 3
let latest_p_id = Product.findOne().sort({ field: 'asc', p_id: -1 }).limit(1);
console.log("p_id" + val); //output should be C3
MongoDB does not natively support incremental auto generated numbers, so your first case, it's not possible if you don't manage your counter separately. You can count the number of documents, but it won't account for deleted documents.
For the second case, you almost got it:
with async/await
const product = await Product.findOne().sort({ p_id: -1 }).limit(1)
console.log(product.p_id) // this will be your desired output
without async/await
Product.findOne().sort({ p_id: -1 }).limit(1).then((product) => {
console.log(product.p_id) // this will be your desired output
})

Sequelize | Node.js, search between two numbers

I'm working on an advanced search with multiple options with Sequelize and Node.js.
One of the options is between two prices.
const search2 = req.body.search2;
const title = req.body.title;
const price = req.body.price;
const prices = req.body.prices;
const prices2 = req.body.prices2;
const address = req.body.address;
Product.findAll({
where: { [Op.and]:
{ price: { [Op.like]: '%' + price + '%' },
category: { [Op.like]: '%' + title + '%' },
description: { [Op.like]: '%' + search2 + '%' },
Renting: { [Op.between]: [prices, prices2] },
address: { [Op.like]: '%' + address + '%' } } }
, order: [['createdAt', 'DESC']], limit, offset
})
const prices and const prices2 are two inputs which the user can write the min and max price.
In my Sequelize model I have column 'Renting' (for renting prices, its INTEGER).
it seems to be that everything is working fine,but the problem is that i get the between prices and prices2 '50' AND '200'. (for example if im searching between 50 and 200).
enter image for example
which is giving me empty results or wrong results for different numbers.
I noticed if i put numbers beside prices and prices2, for example i will write:
Renting: { [Op.between]: [50, 200] },
i will get the right results. 50 AND 200 (without '')
enter image for example
which is good. But it just if I defined the numbers by myself.
Can anyone please help me to find a solution how to get the right result using this two inputs (prices and prices2)?
i think you should convert prices and prices2 to INTEGER before use it in query, and you can update your code
Renting: { [Op.between]: (+prices, +prices2) },
because when you putting '50' , '250' can not match it and return wrong answer.
Just a minor modification to #mohammad javad ahmadi's answer:
Renting: { [Op.between]: [+prices, +prices2] },
Op.between expects array, not tuple.

Resources