Unable to Create Multiple Connect Query in Prisma? - prisma

I am getting this error ForeignKeyConstraintViolation { constraint: Index(\"Device\") } whenever i try to run following query.
const _CreatedConnectedToMobile = await Context.Database.ConnectedToMobile.create({ 'data': {} }) <-- creates entry in db with default values.
// Create mobile entry where i am trying to create entry in Account Table, with Connection to Device and ConnectedToMobile Table.
// Account, Device and ConnectedToMobile -> Mobile(Table) by foriegn key.
await Context.DataBase.mobile.create({
'data': {
'number': mobileNumber,
'Account': {
'create': {
'accountType': _accountType,
'activeAs': _accountType,
'accessPin': accessPin
}
},
'Device': {
'connectOrCreate': {
'where': { deviceUniqueId },
'create': { deviceUniqueId }
}
},
'ConnectedToMobile': {
'connect': {
'id': _CreatedConnectedToMobile.id
}
}
}
})
if i try to run serpratly everythings work fine but shortning it causes error why ?

await Context.DataBase.mobile.create({
'data': {
'number': mobileNumber,
'Account': {
'create': {
'accountType': _accountType,
'activeAs': _accountType,
'accessPin': accessPin
}
},
'Device': {
'connectOrCreate': {
'where': { deviceUniqueId }, // you search by unique Id
// when you create you send object of data
'create': { deviceUniqueId } // the issue here you send the unique Id but this object accept all fields in your schema model except the ID because Id will auto generate by id
}
},
'ConnectedToMobile': {
'connect': {
'id': _CreatedConnectedToMobile.id
}
}
}
})

Related

filter a table with multiple association table column with sequelize node.js

I have given a function, where I want to filter gigs with multiple association table column(actually when I will select Business column name it will show gigs associate with Business and also select GigType column name, gigs will be shown with both association(Business and GigType table) ).
async advanceGigSearch(category, data=null, limit=10, offset=0) {
try {
if(Object.keys(data).length == 0) {
return await Gig.findAndCountAll();
} else {
return await Gig.findAndCountAll({
include:[
{
model:Business,
where: {
...data,
name: {
[Op.iLike]:`%${data.name ? data.name: ""}%`
}
}
},
{
model: GigType,
where: {
...data,
name: {
[Op.iLike]:`%${data.name ? data.name: ""}%`
}
}
},
{
model: GigDetails,
where: {
...data,
name: {
[Op.iLike]:`%${data.name ? data.name: ""}%`
}
}
},
],
order: [["title", "DESC"]],
distinct: true,
limit,
offset,
});
}
} catch(err) {
console(err, `${this.model.name} get`)
throw createError(500);
}
}
I want to filter with multiple association table.

PrismaClientValidationError: Missing required argument in connectOrCreate

Problem:When I try and send/store data in my database I get this error. Specifically, I am trying to create/save a classroom with student names.
Tech Used:
Prisma/Postgres connected to AWS RDS and Next.js, deployed on Vercel, etc.
Error Message
PrismaClientValidationError: Argument data.classrooms.upsert.0.create.students.connectOrCreate.0.create.school.connect of type schoolWhereUniqueInput needs at least one argument.
Argument data.classrooms.upsert.0.update.students.upsert.0.create.school.connect of type schoolWhereUniqueInput needs at least one argument.
at Document.validate (/var/task/node_modules/#prisma/client/runtime/index.js:29501:20)
at serializationFn (/var/task/node_modules/#prisma/client/runtime/index.js:33060:19)
at runInChildSpan (/var/task/node_modules/#prisma/client/runtime/index.js:22550:12)
at PrismaClient._executeRequest (/var/task/node_modules/#prisma/client/runtime/index.js:33067:31)
at async PrismaClient._request (/var/task/node_modules/#prisma/client/runtime/index.js:32994:16)
at async profile (/var/task/.next/server/pages/api/user/profile.js:175:27)
at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils/node.js:366:9)
at async NextNodeServer.runApi (/var/task/node_modules/next/dist/server/next-server.js:481:9)
at async Object.fn (/var/task/node_modules/next/dist/server/next-server.js:735:37)
at async Router.execute (/var/task/node_modules/next/dist/server/router.js:247:36) {
clientVersion: '4.9.0'
}
DB Models with relationships: school (1 to many w/students); students (many to many with classrooms); teachers (one to many with students, many to many with classrooms)
Code/Prisma Query
export default async (req, res) => {
...
classroom.students.forEach((student) => {
const totalStudentPoints = student.rewardsRecieved.reduce(
(totalPoints, reward) => {
return totalPoints + reward.pointValue;
},
0
);
groups[student.group.name] += totalStudentPoints;
});
return { ...classroom, groupsTotalPoints: groups };
});
user.classrooms = newClassrooms;
res.json(user);
} else {
console.log("Could Not Find User");
res.status(401).json({
error: "Not authorized",
});
}
}
if (req.method === "PUT") {
const connectStudents = (shouldUpsert) => {
const students = req.body.students;
return students.map((student) => {
const UNSAFEHASH = md5(student.id);
const studentQuery: any = {
where: {
id: student.id,
},
create: {
id: student.id,
firstName: student.firstName,
lastName: student.lastName,
profilePicture: student.profilePicture,
userKey: UNSAFEHASH,
school: {
connect: {
id: req.body.schoolId,
},
},
group: {
connect: {
id: student.group.id,
},
},
},
};
if (shouldUpsert) {
studentQuery.update = {
firstName: student.firstName,
lastName: student.lastName,
profilePicture: student.profilePicture,
userKey: UNSAFEHASH,
group: {
connect: {
id: student.group.id,
},
},
};
}
return studentQuery;
});
};
try {
const user = await prisma.staff.update({
where: {
id: session.id,
},
data: {
firstName: req.body.firstName,
lastName: req.body.lastName,
classrooms: {
upsert: [
{
where: {
id: req.body.classId || "-1",
},
create: {
// id: req.body.classId,
name: req.body.className,
subject: req.body.classSubject,
students: {
connectOrCreate: connectStudents(false),
},
},
update: {
name: req.body.className,
subject: req.body.classSubject,
students: {
upsert: connectStudents(true),
},
},
},
],
},
},
});
Take a look at the PUT request and the prima.staff.update method more specifically. I was looking at the UPSERT I have there, but I can't figure out what's wrong.

How to create dynamic query in mongoose for update. i want to update multiple data(Not all) with the help of Id

If I'm doing this, the field which I don't want to update is showing undefined. Any solution? (Like generating dynamic query or something)
exports.updateStudentById = async (req, res) => {
try {
const updateAllField = {
first_name: req.body.first_name,
last_name: req.body.last_name,
field_of_study: req.body.field_of_study,
age: req.body.age,
};
const data = await student_master.updateOne(
{ _id: req.body._id },
{ $set: updateAllField }
);
res.json({ message: "Student Data Updated", data: data });
} catch (error) {
throw new Error(error);
}
};
You can go for a dynamic query creation .Example
const requestBody = {
first_name: "John",
last_name: "Cena",
field_of_study: ""
}
const query={};
if(requestBody.first_name){
query["first_name"]=requestBody.first_name
}
if(requestBody.last_name){
query["last_name"]=requestBody.last_name
}
Check for the fields that are present in req.body and create a dynamic query
and when updating using mongoose use this
const data = await student_master.updateOne(
{ _id: req.body._id },
{ $set: query }
);
In this way only those fields would be updated which are present in your req.body

rxjs expand operator with switchMap

I have a list of students, for each student, I have to access the address. I will get the student list in pagination. so I used the 'expand' operator to get all students. but I am not able to get the address for each student.
Student List
{
students: [
{
id: 1,
name: 'ABC'
},
{
id: 2,
name: 'XYZ'
}
],
nextPageToken: 'Aqw12'
}
Now using the student's id I have to fetch the address.
Here is my sample code to get the student's list with the rxjs expand operator.
const connection = this.searchStudent(nextPageToken).pipe(
expand((students: StudentsDto) => {
if (students.nextPageToken){
nextPageToken = students.nextPageToken;
return this.searchStudent(nextPageToken);
}else{
return new Observable as Observable<StudentsDto>;
}
})
);
const subscription = connection.subscribe({
next(response: StudentsDto) {
response.students.forEach(async (student: StudentDto) => {
console.log(student);
});
},
error(e) {
console.log(e)
},
complete() {
subscription.unsubscribe();
},
});
Now I am not able to get, what operator should I apply to get the address.
for address, I have implemented API in this.getAddress(studentId) function which return Observables.
Please help,
Thanks.
const connection = this.searchStudent(nextPageToken).pipe(
expand((response: StudentsDto) => {
if (response.nextPageToken){
nextPageToken = response.nextPageToken;
return this.searchStudent(nextPageToken);
}else{
return new Observable as Observable<StudentsDto>;
}
}),
mergeMap((response: StudentsDto) => {
return response.students.map(student => this.getAddress(student.id))
}),
mergeAll(),
);
const subscription = connection.subscribe({
next(response: AddressDto) {
// Perform/save operation on Address object
},
error(e) {
console.log(e)
},
complete() {
subscription.unsubscribe();
},
});

mongoose When I Use update it updates Nothing with status 200(success)

I use update Query for push some data in array in Mongodb and I use mongoose in nodeJs.Pplease anyone can help out from this.
Model Schema :
var mongoose = require('mongoose')
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt')
var schema = new Schema({
email: { type: String, require: true },
username: { type: String, require: true },
password: { type: String, require: true },
creation_dt: { type: String, require: true },
tasks : []
});
module.exports = mongoose.model('User',schema)
So I use this schema and I want to push data in tasks array and here is my route code for pushing data.
Route For Update Data in Tasks:
router.post("/newTask", isValidUser, (req, res) => {
addToDataBase(req, res);
});
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime,
};
var usr = new User(req.user);
usr.update({ email: req.user.email }, { $push: { tasks: dataa } });
console.log(req.user.email);
try {
doc = await usr.save();
return res.status(201).json(doc);
} catch (err) {
return res.status(501).json(err);
}
}
Here I create a async function and call that function in route but when I post data using postman it response with status code 200(success) but it updates nothing in my database.
Output screenshot:
as you can see in this image task : [].. it updates nothing in that array but status is success
I don't know why is this happening.
You can achieve this task easier using findOneAndUpdate method.
router.put("/users", isValidUser, async (req, res) => {
var data = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime,
};
try {
const user = await User.findOneAndUpdate(
{ email: req.user.email },
{
$push: {
tasks: data,
},
},
{ new: true }
);
if (!user) {
return res.status(404).send("User with email not found");
}
res.send(user);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
});
Also I strongly suggest using raw / JSON data for request body, that's how most ui libraries (reactjs, angular) send data.
To be able to parse json data, you need to add the following line to your main file before using routes.
app.use(express.json());
TEST
Existing user:
{
"tasks": [],
"_id": "5e8b349dc285884b64b6b167",
"email": "test#gmail.com",
"username": "Kirtan",
"password": "123213",
"creation_dt": "2020-04-06T14:21:40",
"__v": 0
}
Request body:
{
"pName": "pName 1",
"pTitle": "pTitle 1",
"pStartTime": "pStartTime 1",
"pEndTime": "pEndTime 1",
"pSessionTime": "pSessionTime 1"
}
Response:
{
"tasks": [
{
"pName": "pName 1",
"pTitle": "pTitle 1",
"pStartTime": "pStartTime 1",
"pEndTime": "pEndTime 1",
"pSessionTime": "pSessionTime 1"
}
],
"_id": "5e8b349dc285884b64b6b167",
"email": "test#gmail.com",
"username": "Kirtan",
"password": "123213",
"creation_dt": "2020-04-06T14:21:40",
"__v": 0
}
Also as a side note, you had better to create unique indexes on username and email fields. This can be done applying unique: true option in the schema, but better to create these unique indexes at mongodb shell like this:
db.users.createIndex( { "email": 1 }, { unique: true } );
db.users.createIndex( { "username": 1 }, { unique: true } );
It's been awhile since I've done mongoose, but I'm pretty sure <model>.update() also actively updates the record in Mongo.
You use .update() when you want to update an existing record in Mongo, but you are instantiating a new User model (i.e. creating a new user)
try the following code instead for a NEW USER:
router.post('/newTask', isValidUser, (req, res) => {
addToDataBase(req,res)
})
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime
}
// email field is already in `req.user`
var usr = new User({ ...req.user, tasks: [dataa] });
console.log(req.user.email);
try {
await usr.save();
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
}
Now, if you wanted to update an existing record :
router.post('/newTask', isValidUser, (req, res) => {
addToDataBase(req,res)
})
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime
}
try {
await usr. updateOne({ email : req.user.email}, { $push: { tasks: dataa } });
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
}
For more info read: https://mongoosejs.com/docs/documents.html