How to find the field that caused the error - prisma2

I am trying to find the field that has an error as described on this page:
https://www.prisma.io/docs/reference/api-reference/error-reference
More specifically: PrismaClientKnownRequestError, meta Additional information about the error - for example, the field that caused the error: { target: [ 'email' ] }
I can not seem to log meta.target, instead I get undefined.
This is the sample code from the docs.
import { PrismaClient, Prisma } from '#prisma/client'
const client = new PrismaClient()
try {
await client.user.create({ data: { email: 'alreadyexisting#mail.com' } })
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
// The .code property can be accessed in a type-safe manner
if (e.code === 'P2002') {
console.log(
'There is a unique constraint violation, a new user cannot be created with this email'
)
}
}
throw e
}
How do I get access to target?
Many thanks
Paul

Related

MongoDB : "message": "Cannot read properties of undefined (reading 'findById')"

I am creating api i get this error in postman "message": "Cannot read properties of undefined (reading 'findById')"
async function getCustomer(req, res, next) {
let Customer
try {
Customer = await Customer.findById(req.params,id)
if (Customer == null) {
return res.status(404).json({ message: 'Cannot find Customer' })
}
} catch (err) {
return res.status(500).json({ message: err.message })
}
res.Customer = Customer
next()
}
any help please?
The problem is
let Customer
When calling Customer.findById() the local Customer will be called (the one declared with let).
Name the customer with a small letter i.e
let customer
customer = await Customer.findById()...

need to create a mongoose transaction wrapper which will pass session as parameter to functions that actually do query operations to create or update

So lets say i have a function that takes care of user creation which was previously available to us. Now we just want the function to work in the form of one transaction that creates all users together if success or fails completely when it encounters any error. I am assuming passing just the session to the existing function from the transaction wrapper should take care of this. Any number of such function can be passed together and the wrapper should handle them all as a single transaction.
const createUsers = async (users = []) => {
try {
return UserModel.create(users).then((res) => {
logger.info(`[Start-Up] Created ${res.length} users`);
}, (rej) => {
logger.error(`[Start-Up] Failed to create users - ${rej}`);
throw new Error(rej);
});
} catch (err) {
throw new Error('Failed to create Users', err);
}
};
Use https://www.npmjs.com/package/mongoose-transactions
https://mongoosejs.com/docs/transactions.html
const createUsers = async (users = []) => {
const session = await UserModel.startSession();
try {
await session.withTransaction(() => {
return UserModel.create(users, { session: session }).then((res) => {
logger.info(`[Start-Up] Created ${res.length} users`);
}, (rej) => {
logger.error(`[Start-Up] Failed to create users - ${rej}`);
throw new Error(rej);
});
});
} catch (err) {
throw new Error('Failed to create Users', err);
} finally {
session.endSession();
}
};

.find() returning nothing even when data exists

I've a mongo database with 3 collections for 3 different kind of users as User,Partner,Admin. Whenever a new user of any type signup I'm searching all three collections to check if username and email exist already. I'm trying to achieve this by calling a function as:
function checkAttribute(attr,val,callback){
User.find({attr: val},function(err,user){
if(err){
console.log(err);
}else{
if(user.length === 0){
Partner.find({attr: val},function(err,partner){
if(err){
console.log(err);
}else{
if(partner.length === 0){
Admin.find({attr: val},function(err,admin){
if(err){
console.log(err);
}else{
if(admin.length === 0){
return callback(null,true);
}else{
return callback(null,false);
}
}
});
}else{
return callback(null,false);
}
}
});
}else{
return callback(null,false);
}
}
});
};
Calling function line:
checkAttribute("username",newUser.username,function(error,response){
.......
});
But this is not working as it returns true always even when users with passed username/email exists already. I am unable to find the problem. Any one knows why this is happening?
Thanks in advance.
Since you are passing in the attribute as a variable in the function parameters, the query document
{ attr: val } is an object with the key "attr", not the dynamic attribute you pass in.
To fix this, you need to use computed property names in your query object as
{ [attr]: val }
Also, the function can use async/await pattern to be more readable and for the purpose of finding if a document exist findOne does the job so
well as it returns a document if it exists and null otherwise.
So your function can be refactored as
async function checkAttribute(attr, val, callback) {
try {
const query = { [attr]: val }
const user = await User.findOne(query).exec()
const partner = await Partner.findOne(query).exec()
const admin = await Admin.findOne(query).exec()
const found = (user || partner || admin) ? true: false
return callback(null, found)
} catch (err) {
console.error(err)
return callback(err, null)
}
};
attr: in your queries will search for a db field called attr. If you want to use the function parameter attr, use [attr]: as the key.
Example:
attr = 'username'
User.find({ [attr]: val }, function (err, user) {
if (err) {
console.log(err);
}
})
This is a feature available since ES6 so should work fine. See the docs here for more info

Loopback - How to use bulkUpdate method

I'm using Loopback v3 currently and wanted to upsert many records at once in a collection; I found this method bulkUpsert from the documentation (http://apidocs.loopback.io/loopback/#persistedmodel-bulkupdate) but I couldn't figure out how to make it work.
How can I create the updates array from createUpdates() method as mentioned in the documentation? Can anyone help me with a simple example of using this method?
There is an alternative way to do the bulkUpdate method, found in Stackoverflow MongoDB aggregation on Loopback
A mixin can be easily created and reused over the Models. My sample code of bulkUpsert mixin is below:
Model.bulkUpsert = function(body, cb) {
try {
Model.getDataSource().connector.connect(async (err, db) => {
if (err) {
return cb(err);
}
// Define variable to hold the description of the first set of validation errors found
let validationErrors = '';
// Build array of updateOne objects used for MongoDB connector's bulkWrite method
const updateOneArray = [];
// Loop through all body content and stop the loop if a validation error is found
const hasError = body.some(row => {
// Check if it is a valid model instance
const instance = new Model(row);
if (!instance.isValid()) {
// A validation error has been found
validationErrors = JSON.stringify(instance.errors);
// By returning true we stop/break the loop
return true;
}
// Remove ID in the row
const data = JSON.stringify(row);
delete data.id;
// Push into the update array
updateOneArray.push({
updateOne: {
filter: { _id: row.id },
update: { $set: Object.assign({ _id: row.id }, data) },
upsert: true
}
});
// No validation error found
return false;
});
// Check if a validation error was found while looping through the body content
if (hasError) {
return cb(new Error(validationErrors));
}
// No validation data error was found
// Get database collection for model
const collection = db.collection(Model.name);
// Execute Bulk operation
return collection.bulkWrite(updateOneArray, {}, (err, res) => {
// Check if the process failed
if (err) {
console.err('The bulk upsert finished unsuccessfully', err);
return cb(err);
}
// Check if there were errors updating any record
if (res.hasWriteErrors()) {
console.error(`The bulk upsert had ${res.getWriteErrorCount()} errors`, res.getWriteErrors());
}
// Finished successfully, return result
return cb(null, {
received: body.length,
handled: res.upsertedCount + res.insertedCount + res.matchedCount
});
});
});
}
catch (err) {
console.error('A critical error occurred while doing bulk upsert', err);
return cb(err);
}
return null;
};
Ref: Mongodb query documentation

How can I pass last stream value to error handler?

Let's say I have the following synchronous code that requires original arguments when handling errors:
var input = createInput(123);
try {
doWork(input);
} catch (err) {
handleError(input, err); // error handling requires input
}
What is the best way to pass the original arguments to the error hander?
Rx.Observable.just(123).map(createInput).map(doWork).subscribe(
function(result) {
// success
},
function(err) {
// how can I get the argument of doWork (the result of createInput) here?
}
);
Just add it as a property of the Error object before you throw it or in wrapper code like below.
...map(function (value) {
try {
return createInput(value);
}
catch (e) {
e.lastValue = value;
throw e;
}
}).subscribe(..., function (e) {
e.lastValue...