How to retrieve a sub query in prisma client with same table? - node.js

select *
from WeeklyChallengeCourses
where weekly_challenge_id = (select weekly_challenge_id
from WeeklyChallengeCourses
where course_id = 210);
Result will be the below selected one:
const data = await context.prisma.weeklyChallengeCourses.findMany({
where:{
weekly_challenge_id: {
..............
}
},
});

In Prisma, you would have to use two different queries to solve this:
Run an equivalent of the subquery to fetch the weekly_challenge_id
Run a findMany with the weekly_challenge_id found in step 1.
// I'm assuming course_id is unique.
const course = await context.prisma.findUnique({ where: { course_id: 210 } });
const data = await context.prisma.weeklyChallengeCourses.findMany({
where:{
weekly_challenge_id: course.weekly_challenge_id
},
});
Alternatively, you could use the rawQuery feature to run the SQL directly and do it in one query.

Related

How can i use not or != in nestjs

I want to compare to ids one in relation and the other given by me in a query and get all information, for example:
async getAllPhoto(id: string) {
var photo = await this._photoRepository.find({
relations: {
catalogue: true,
},
where: { catalogue: { id: Not(id) } },
});
return photo;
}
I tried this but got an empty array.
const ids = 2; // get your id which you request from font-end
const photo = this.repository.find({
relations:['catalogue'],
where:{
catalogue:{
id: Not(ids)
}
}
})
when you develop project in nestjs,
you'd better enable "logging":true in your database config!
you will find all raw sql from ORM.

Mongoose: After finding document, iterate over a value in the document and run a new query on each

I have one schema which contains an array of references to another schema (among other fields):
const RecipeIngredient = new Schema({
ingredientId: { // store id ref so I can populate later
type: Schema.Types.ObjectId,
ref: 'ingredients',
required: true
},
// there are a couple other fields but not relevant here
});
const Recipe = new Schema({
ingredients: [RecipeIngredient]
});
I'm trying to write a route which will first find a recipe by _id, populate the ingredients array (already have this working), and finally iterate over each ingredient in that array.
router.get('/:recipeId/testing', async (req, res) => {
const { recipeId } = req.params
let recipe = await Recipe
.findById(recipeId)
.populate({
path: 'ingredients.ingredientId',
model: 'Ingredient',
select: '_id ......' //I'm selecting other fields too
})
.lean()
.exec();
if (recipe) {
const { ingredients } = recipe;
const newIngredients = [];
await ingredients.forEach(async (ingr) => {
// here I'd like to be able to run a new query
// and append the result to an array outside of the forEach
// I do need information about the ingr in order to run the new query
newIngredients.push(resultOfNewQuery);
});
return res.json(newIngredients)
};
return res.status(404).json({ noRecipeFound: 'No recipe found.'});
})
I've tried approaching this in a few different ways, and the closest I've gotten was executing the new query within each iteration, but because the query is async, I return the response before I've actually collected the documents from the inner query.
I also attempted to use .cursor() in the initial query, but that won't work for me because I do need to access the ingredients field on the recipe once it is resolved before I can iterate and run the new queries.
Any ideas would be appreciated! I'm definitely opening to restructuring this whole route if my approach is not ideal.
I was able to make this work by using a for loop:
const newIngredients = [];
for (let idx = 0; idx < ingredients.length; idx++) {
const { fieldsImInterestedIn } = ingredients[idx];
const matchingIngredients = await Ingredient
.find(fieldsImInterestedIn)
.lean()
.exec()
.catch(err => res.status(404).json({ noIngredientsFound: 'No ingredients found' }));
newIngredients.push(ingredientsToChooseFrom[randomIndex]);
};
return res.json(newIngredients);
still a little perplexed as to why this was able to work while forEach wasn't, but I'll happily move on...

How to use MongoDB $ne on nested object property

I have a node API which connects to a mongoDB through mongoose. I am creating an advanced results middleware that enabled selecting, filtering, sorting, pagination etc. based on a Brad Traversy course Node.js API Masterclass With Express & MongoDB. This is all good.
I am adapting the code from the course to be able to use the $ne (not equal) operator and I want to be able to get a model that is not equal to a nested property (user id) of the model. I am using this for an explore feature to see a list of things, but I don't want to show the user their own things. I am having trouble figuring out how to access the id property.
********************* UPDATE *********************
It seems all the documentation I've read recommends writing const injected like this:
const injected = {
'user._id': { "$ne": req.user.id }
};
but for some reason it is not working. I can query top level properties that are just a plain string value like this:
const injected = {
access: { "$ne": "public" }
};
but not a property on an object. Does anyone know why? Is it because the property I want to query is an id? I've also tried:
const injected = {
'user._id': { "$ne": mongoose.Types.ObjectId(req.user.id) }
};
which also does not work...
So the model looks like this:
{
name: 'Awesome post',
access: 'public',
user: {
_id: '2425635463456241345', // property I want to access
}
}
then the actual advanced results middleware looks like this and it's the 'injected' object where I am trying to access id. In the course brad uses this syntax to use lte (/?averageCost[lte]=10000) but I do not get any results with my ne. Can anyone help me here?
const advancedResults = (model, populate) => async (req, res, next) => {
let query;
const injected = {
access: 'public',
'user._id[ne]': req.user.id, // I don't think user._id[ne] is correct
};
}
// Copy req.query
const reqQuery = { ...req.query, ...injected };
console.log('injected: ', injected);
// Fields to exclude
const removeFields = ['select', 'sort', 'page', 'limit'];
// Loop over removeFields and delete them from reqQuery
removeFields.forEach(param => delete reqQuery[param]);
// Create query string
let queryStr = JSON.stringify(reqQuery);
// Create operators ($gt, $gte, etc)
queryStr = queryStr.replace(/\b(gt|gte|lt|lte|in|ne)\b/g, match => `$${match}`);
// Finding resource and remove version
query = model.find(JSON.parse(queryStr)).select('-__v');
// Select Fields
if (req.query.select) {
const fields = req.query.select.split(',').join(' ');
query = query.select(fields);
}
// Sort
if (req.query.sort) {
const sortBy = req.query.sort.split(',').join(' ');
query = query.sort(sortBy);
} else {
query = query.sort('-createdAt');
}
// Pagination
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 25;
const startIndex = (page - 1) * limit;
const endIndex = page * limit;
const total = await model.countDocuments(JSON.parse(queryStr));
query = query.skip(startIndex).limit(limit);
if (populate) {
query = query.populate(populate);
}
// Executing query
const results = await query;
// Pagination result
const pagination = {};
if (endIndex < total) {
pagination.next = {
page: page + 1,
limit,
};
}
if (startIndex > 0) {
pagination.prev = {
page: page - 1,
limit,
};
}
res.advancedResults = {
success: true,
count: results.length,
pagination,
data: results,
};
next();
};
module.exports = advancedResults;
Answering your question about how to use $ne:
The use of $ne is as follows:
"field":{
"$ne": yourValue
}
Into your query should be like:
"user._id": {
"$ne": req.user.id
}
Example here
$ne operator will return all document where the field value don't match with the given value.
As you have done, to acces the nested field is necessary use the dot notation.
Also, to ensure it works, if your schema defines _id as ObjectId maybe is necessary parse req.user.id to ObjectId.
But if in your schema is a string then should works.
So try (not tested at all):
const injected = {
'user._id': { "$ne": req.user.id }
};

POST the same UUID into two tables with Node / PostgreSQL

I am trying to make a POST request that will insert the same UUID value into two tables: 'employee' and 'skill'. I have tried this a few different ways, but have not been able to do so. Here is my query for posting the UUID (and a 'summary') into one table:
app.post("/employees/:id/skills", async(req, res) => {
try {
const { summary } = req.body;
const addEmployeeSkill = await pool.query(
"INSERT INTO skill(skill_uuid, summary)VALUES(uuid_generate_v4(), $1) RETURNING *",
[summary],
);
res.json(addEmployeeSkill.rows[0]);
} catch (err) {
console.error(err.message);
}
});
My question is: how do I get the same UUID that is being generated into the 'skill' table to also insert into the skill_uuid column of the 'employee' table?

postgres SELECT query returns unusable result

I have a simple SELECT query that is returning an unusable result. I am using pg-promise in node.js
[
{
"function_name": "(f10d1988-4db5-49de-97ab-0c8b15bedfa7,image.jpg,Image)"
},
{
"function_name": "(f10d1988-4db5-49de-97ab-0c8b15bedfa7,image2.jpg,Image 2)"
}
]
but I was expecting a basic json structure like
[
{
id: '',
title: '',
image: ''
},
{...etc}
]
Why is it doing this? How do I get a normalized result?
My query looks like the below:
CREATE OR REPLACE FUNCTION get_photos(
title_param TEXT
)
RETURNS TABLE(
id UUID,
image varchar(200),
title varchar(200)
) AS
$func$
BEGIN
RETURN QUERY SELECT
i.id,
i.image,
i.title
FROM images AS i
WHERE i.title = title_param;
END;
$func$ LANGUAGE PLPGSQL;
Here is my db conenctor setup, almost all defaults.
require('dotenv').config();
const Promise = require('bluebird');
const pg = require('pg-promise')({
promiseLib: Promise
});
const config = {
user: process.env.USER,
host: process.env.HOST,
database: process.env.DATABASE,
password: process.env.PASSWORD
};
const db = pg(config);
export default db;
Here is the express endpoint that is calling the function:
export const getData = async (req, res) => {
const { title } = req.query;
let data;
try {
data = await db.many('SELECT function_name($1)', [title]);
} catch (err) {
data = err;
}
res.send(data);
};
EDIT
I ran the query manually instead of through a function and the data returned correctly which means that there is an issue with my TABLE() return. What could possibly cause this issue?
images = await db.many(`
SELECT
p.id,
p.img,
p.type,
p.title
FROM photos p
WHERE p.type = '${type}';
`, [type]);
Because the function is defined as returning a table, you need to use it like a table:
SELECT * FROM function_name($1)
Use func as the query method:
data = await db.func('function_name', [title]);
It assumes you return a table, and so will work for you by default.
And for stored procedures, there's proc method.
Also, your parameter formatting for the images query is wrong, see Named Parameters:
IMPORTANT: Never use the reserved ${} syntax inside ES6 template strings ...

Resources