How to select a UUID from a prepared statement in Postgres? - node.js

I'm trying to select a user based on a UUID:
const client = await this.pg.connect()
const { rowsAct } = await client.query(`SELECT * FROM users WHERE uid=$1`, [
userUUID
])
I also tried without the variable:
const client = await this.pg.connect()
const { rowsAct } = await client.query(`SELECT * FROM users WHERE uid=$1`, [
'4fcf0ca3-4e26-40a9-bbe5-78ff8fdb6e0f'
])
I tried using ::uuid casting but maybe I did it wrong. The returned rowsAct is always undefined.
I verified the userUUID variable was populated and was a valid uuid:
console.log(typeof userUUID) // string
What am I doing wrong? How can I properly select a row form it's UUID?
Thanks!

You'll need to wrap your argument in parentheses before applying the ::uuid type cast so that the prepared statement can properly interpolate argument.
SELECT * FROM users WHERE uid = ($1)::uuid
You can also cast the column itself to text but it's less performant since the query will have to cast each row.
SELECT * FROM users WHERE uid::text = $1

Related

How to prevent injection for my postgres query in node?

Below is my code base with the query
export const getQuery = (idList) => {
return `SELECT * from glacier_restore_progress where id in ${idList}`;
}
const query = getQuery('(1,2)');
dbResponse = await pool.query(query)
...
it works fine. But the Sql Injection issue is popping from my sonar server.
So i tried below code change and it didn't work,
...
dbResponse = await pool.query('SELECT * from glacier_restore_progress where id in $1', ['(1,2)']);
What am i missing here?
The best solution uses the ANY function with Postgres array coercion. This lets you match a column with an arbitrary array of values as if you had written out col IN (v1, v2, v3). This is the approach in pero's answer.
SELECT * FROM glacier_restore_progress WHERE id = ANY($1::int[])
dbResponse = await pool.query('SELECT * FROM glacier_restore_progress WHERE id = ANY($1::int[])', [[1,2, ...]]);

Mongoose, NodeJS & Express: Sorting by column given by api call

I'm currently writing a small API for a cooking app. I have a Recipe model and would like to implement sorting by columns based on the req Parameter given.
I'd like to sort by whatever is passed in the api call. the select parameter works perfectly fine, I can select the columns to be displayed but when I try to sort anything (let's say by rating) the return does sort but I'm not sure what it does sort by.
The code i'm using:
query = Recipe.find(JSON.parse(queryStr));
if(req.query.select){
const fields = req.query.select.split(',').join(' ');
query = query.select(fields);
}
if(req.query.sort){
const sortBy = req.query.sort.split(',').join(' ');
query = query.sort({ sortBy: 1 });
} else {
query = query.sort({ _id: -1 });
}
The result, when no sorting is set: https://pastebin.com/rPLv8n5s
vs. the result when I pass &sort=rating: https://pastebin.com/7eYwAvQf
also, when sorting my name the result is also mixed up.
You are not using the value of sortBy but the string "sortBy". You will need to create an object that has the rating as an object key.
You need the sorting object to look like this.
{
rating: 1
}
You can use something like this so it will be dynamic.
if(req.query.sort){
const sortByKey = req.query.sort.split(',').join(' ');
const sortByObj = {};
sortByObj[sortByKey] = 1; // <-- using sortBy as the key
query = query.sort(sortByObj);
} else {
query = query.sort({ _id: -1 });
}

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 data by id from firebase

I use firebase on node.js .
My given structure should look like this:
{
...
batch-1:
id-1(suppose):
name:...
phone:...
id-2:
...
id-3:
...
batch-2:
...
batch-3:
...
...
batch-n:
...
}
How can I get an id-1 object by its identifier in such an architecture?
Does the database have to go around all the batches?
Is there a better solution?
The main task: Create a batch with many objects that will have SHORT and a UNIQUE identifier and optimally receive data by this identifier
To search for a particular ID that is a child of a list of unknown IDs, you need to use orderByChild(). In your use case, you are looking for a particular ID in a list of batch IDs. If you used orderByChild() on this list, you would get back results for each and every batch ID, even if it didn't have the ID you wanted. This is because even null (non-existant) values are included (and sorted at the start) in the results. To get the data of the desired ID, you would get the data for the last result of the query, which if it existed, would be sorted to the end of the list. Note that if the desired ID doesn't exist, the last result (if there are any results) would have a null value. To return only the last result of the query, you would use limitToLast(1).
Putting this all together, gives the following code:
let idToFind = "unique-id-1";
let batchesRef = firebase.database().ref(); // parent key of "batch-1", "batch-2", etc.
// assumed to be the database root here
batchesRef.orderByChild(idToFind).limitToLast(1).once('value')
.then((querySnapshot) => {
if (!querySnapshot.numChildren()) { // handle rare no-results case
throw new Error('expected at least one result');
}
let dataSnapshot;
querySnapshot.forEach((snap) => dataSnapshot = snap); // get the snapshot we want out of the query's results list
if (!dataSnapshot.exists()) { // value may be null, meaning idToFind doesn't exist
throw new Error(`Entry ${idToFind} not found.`);
}
// do what you want with dataSnapshot
console.log(`Entry ${idToFind}'s data is:`, dataSnapshot.val());
})
.catch((error) => {
console.log("Unexpected error:", error);
})
For small data sets, the above code will work just fine. But if the list of batches starts growing quite large, you may wish to build an index that maps a particular ID to the batch ID that contains it.
Here is my method which allows you to search by id or to search by key value such as email uniqueemail
// gets primary key
const getSnapshotValKey = snapshot => (Object.keys(snapshot).length > 0 ? Object.keys(snapshot)[0] : null)
const getUser = async ({ id, key, value }) => {
let user = null
const ref = id ? '/users/' + id : 'users'
const userRef = admin.database().ref(ref)
const valueRef = id ? userRef : await userRef.orderByChild(key).equalTo(value)
const snapshot = await valueRef.once('value')
const val = snapshot.val()
if (val) {
const key = id || getSnapshotValKey(val)
user = {
id: key,
...(id ? val : val[key]),
}
}
return user
}

remove user id from array of object ids

i have four object ids in an array . i also have a user id. i would like to remove the user id from array of object ids
allowners= [ 5d6caefdbb6f2921f45caf1d, 5d6caee9bb6f2921f45caf1b,
5d6dfcd6e3b11807944348b8, 5d6caefdbb6f2921f45caf1d]
user._id = 5d6caefdbb6f2921f45caf1d
what i tried
const userid = user._id
const vendors = allowners.filter((item) => userid !== item)
The result i got is
vendors = [ 5d6caefdbb6f2921f45caf1d,
5d6caee9bb6f2921f45caf1b,
5d6dfcd6e3b11807944348b8,
5d6caefdbb6f2921f45caf1d ]
the result i am expecting is
vendors = [ 5d6caee9bb6f2921f45caf1b,5d6dfcd6e3b11807944348b8]
If these ids in allowners array are Mongoose ObjectID you'll need to use .equals method on the ObjectID object to compare:
user._id = "5d6caefdbb6f2921f45caf1d"; //even if this is an ObjectID of mongoose
const userid = user._id;
const vendors = allowners.filter(item => !item.equals(userid));
Another Way: Using toString() on ObjectID (will only work when compared to a string -- userid)
vendors = allowners.filter(item => item.toString() !== userid);
Output:
console.info("Filtered IDs::", vendors);
Filtered IDs:: [ 5d6caee9bb6f2921f45caf1b, 5d6dfcd6e3b11807944348b8 ]
Your result should compute to the expected result if your data type match properly. For example:
// Your array of IDs of type {String}
const allowners = ['5d6caefdbb6f2921f45caf1d', '5d6caee9bb6f2921f45caf1b', '5d6dfcd6e3b11807944348b8', '5d6caefdbb6f2921f45caf1d'];
// Your user object with an id of type {String}
const userObject = {
id: '5d6caefdbb6f2921f45caf1d'
}
// Extract the id from your user object, and store in a userId variable If you wish :-)
const userId = userObject.id;
// Using your code with just changes in the variable name (userid -> userId)
const vendors = allowners.filter((item) => userId !== item);
// The result
console.log(vendors); // [ '5d6caee9bb6f2921f45caf1b', '5d6dfcd6e3b11807944348b8' ]

Resources