Sequelize - get proper path while validating associations of a model - node.js

I'm using Sequelize as an ORM for my project. I have this structure:
const Event = sequelize.define('event', {
// fields defined
});
const Question = sequelize.define('question', {
description: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Description should be set.' }
},
},
// other fields defined
});
Event.hasMany(Question);
Question.belongsTo(Event);
Then I create an instance of the Event model, with associate, like that:
const body = {
questions: [
{ description: '' } // is obviously invalid
],
// some other fields
}
const newEvent = await Event.create(body, {
include: [ Question ]
});
If I have validation errors for the Event instance itself, it returns SequelizeValidationError where I can see the path attribute for each ValidationErrorItem. However, when I have the validation error on a child model, the path attribute for this validation error is unclear:
{
"message": "Description should be set.",
"type": "Validation error",
"path": "description",
"value": "",
"origin": "FUNCTION",
"instance": {
"required": true,
"id": null,
"description": "",
"event_id": 60,
"updated_at": "2018-06-11T12:25:04.666Z",
"created_at": "2018-06-11T12:25:04.666Z"
},
"validatorKey": "notEmpty",
"validatorName": "notEmpty",
"validatorArgs": [
{
"msg": "Description should be set."
}
],
"__raw": {
"validatorName": "notEmpty",
"validatorArgs": [
{
"msg": "Description should be set."
}
]
}
The problem is, it's unclear what caused this error and which child is invalid. When I've used Mongoose as an ORM, if I'd do the same, the path attribute would be equal to something like questions.0.description, and that is way more clear, that way you can see which child is invalid.
So, my question is: is there a way to set up the path attribute while validating the child models?

Apparently it's not presented yet, I've filed an issue on Sequelize repo, here it is: https://github.com/sequelize/sequelize/issues/9524

Related

Remove object from nested array in MongoDB using NodeJS

I can see that this question should have been answered here, but the code simply doesn't work for me (I have tried multiple, similar variations).
Here is my data:
[{
"_id": {
"$oid": "628cadf43a2fd997be8ce242"
},
"dcm": 2,
"status": true,
"comments": [
{
"id": 289733,
"dcm": 2,
"status": true,
"clock": "158",
"user": "Nathan Field",
"dept": "IT",
"department": [],
"dueback": "",
"comment": "test 1"
},
{
"id": 289733,
"dcm": 2,
"status": true,
"clock": "158",
"user": "Nathan Field",
"dept": "IT",
"department": [],
"dueback": "",
"comment": "test 2"
}
],
"department": [],
"dueback": ""
}]
And here is my code
const deleteResult = await db.collection('status').updateOne(
{ "dcm": comments.dcm },
{ $pull: { "comments": { "id": comments.id } } },
{ upsert: false },
{ multi: true }
);
Absolutely nothing happens...
So the issue ended up being something to do with running multiple update operations within one function. I have a database connection function like this:
const withDB = async (operations, res) => {
try {
const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
const db = client.db('collection');
await operations(db);
client.close();
} catch (error) {
res.status(500).json({ message: 'Error connecting to db', error });
}
}
And then I call this by using:
withDB(async (db) => {
await db.collection('status').updateMany(
{ "dcm": comments.dcm },
{ $pull: { "comments": { "id": comments.id } } },
{ multi: true }
);
});
The issue occurred it would seem because I had two of these update operations within one withDB function. I have multiple operations in other instances (update item, then fetch collection), but for some reason this caused an issue.
I created a separate call to the withDB function to perform the '$pull' (delete) request, and then updated the array with the new comments.
To check that there was nothing wrong with my actual query, I used Studio3T's IntelliShell feature. If I'd done that sooner I would saved myself a lot of time!

Update numeric and float fields in elasticsearch client

I am bit new to elasticsearch client.
I have not done any type of predefined mapping to any field, because I might add some new field to the documents in future.
My data looks like this:-
{
"segmentId": "4700-b70e-881",
"segmentName": "test",
"data": "This is a test data",
"dataId": "70897e86-9d69-4700-b70e-881a7f74e9f9",
"augmented": false,
"createdBy": {
"email": "2010abinas#gmail.com",
"primaryKey": "902d2b57-54e6",
"secondaryKey": "adcc-f20423822c93"
},
"status": "active",
"createdAt": 1617422043554,
"updatedAt": 1617422043554
}
I wanted to update 3 fields by using updateByQuery.
I was trying below approach.
await esClient.updateByQuery({
index: "data",
type: "doc",
refresh: true,
body:{
query:{
match: {
dataId: "70897e86-9d69-4700-b70e-881a7f74e9f9"
}
},
script:{
lang:"painless",
source:`ctx._source.data='This is updated test data';ctx._source.updatedAt=${Date.now()};ctx._source.segmentId=null`
}
}
})
I am getting compilation error because of updatedAt and segmentId, When I pass as string it works, like:-
source:`ctx._source.data='This is updated test data';ctx._source.updatedAt='${Date.now()}';ctx._source.segmentId='null'`
I found a way to solve the above issue,
await esClient.updateByQuery({
index: "data",
type: "doc",
refresh: true,
body:{
query:{
match: {
dataId: "70897e86-9d69-4700-b70e-881a7f74e9f9"
}
},
script:{
lang:"painless",
source:`ctx._source.data='This is updated test data';ctx._source.updatedAt=params.date;ctx._source.segmentId=params.segmentId`,
params:{
date: Date.now(),
segmentId: null
}
}
}
});

Swagger Nest.js ValidationPipe ApiBadRequestResponse

👋I just started playing around with Swagger and everything is amazing. I was able to document all API in an hour or so but I got stuck solving one last issue.
How can I tell swagger to show ApiBadRequestResponse in the format below?
#ApiOkResponse({
type: User,
})
#ApiBadRequestResponse({
type: {
error: String,
message: ValidationError[]
}
})
#Post('/signup')
signUp(
#Body(ValidationPipe) authCredentialsDto: CredentialsDTO
): Promise<User> {
return this.userService.signUp(authCredentialsDto)
}
From what I understand swagger doesn't know how to work with interfaces instead I have to use classes. Is there a simple way to document bad request response triggered by ValidationPipe. This is all native #nestjs behavior so I would assume there must be an easy solution.
This is what gets actually returned from API:
"statusCode": 400,
"error": "Bad Request",
"message": [
{
"target": {
"username": "somename",
"password": "****"
},
"value": "****",
"property": "password",
"children": [], // ValidationError[]
"constraints": {
"matches": "password too weak"
}
}
]

Not able to query for nested relations using dgraph-orm

I am using dgraph-orm for fetching nested relational values but it works for single level but not multiple level.
I am getting the page details but unable to fetch the avatar of the page.
Here is my snippet:
let posts = await PagePost.has('page_id', {
filter: {
page_id: {
uid_in: [page_id]
}
},
include: {
page_id: {
as: 'page',
include: {
avatar: {
as: 'avatar'
}
}
},
owner_id: {
as: 'postedBy'
}
},
order: [], // accepts order like the above example
first: perPage, // accepts first
offset: offset, // accepts offset
});
I am not getting avatar for the attribute page_id:
{
"uid": "0x75b4",
"title": "",
"content": "haha",
"created_at": "2019-09-23T08:50:52.957Z",
"status": true,
"page": [
{
"uid": "0x75ac",
"name": "Saregamaapaaaa...",
"description": "This a is place where you can listen ti thrilling music.",
"created_at": "2019-09-23T06:46:50.756Z",
"status": true
}
],
"postedBy": [
{
"uid": "0x3",
"first_name": "Mohit",
"last_name": "Talwar",
"created_at": "2019-07-11T11:37:33.853Z",
"status": true
}
]
}
Is there a support for multilevel field querying in the orm??
There was some issue with ORM itself it was not able to recognize the correct model name for multilevel includes and generating the wrong queries.
Fixed the same in version 1.2.4, please run npm update dgraph-orm --save to update your DgraphORM.
Thanks for the issue.

Best way to wrap mongoose validation error

We know that mongoose provides us an easy way to do validation. But suppose you are using express+mongoose to building a microservice; and some clients (could be web-app, mobile app etc.) needs to consume it.
Usually, I prefer to response JSON back with simple error code and message. In most cases, the clients who can create their own messages depending on which language they are showing to users.
By default, if we catch the error from mongoose, we can get JSON response such as:
JSON Response
{
"errors": {
"price": {
"message": "Path `price` (-1) is less than minimum allowed value (0).",
"name": "ValidatorError",
"properties": {
"min": 0,
"type": "min",
"message": "Path `{PATH}` ({VALUE}) is less than minimum allowed value (0).",
"path": "price",
"value": -1
},
"kind": "min",
"path": "price",
"value": -1,
"$isValidatorError": true
},
"code": {
"message": "Product with given code already exists",
"name": "ValidatorError",
"properties": {
"type": "user defined",
"message": "Product with given code already exists",
"path": "code",
"value": "p-1000"
},
"kind": "user defined",
"path": "code",
"value": "p-1000",
"$isValidatorError": true
}
},
"_message": "Product validation failed",
"message": "Product validation failed: price: Path `price` (-1) is less than minimum allowed value (0)., code: Product with given code already exists",
"name": "ValidationError"
}
Restful Api Controller
exports.createOne = async(function* list(req, res) {
try {
const product = new Product(req.body)
const newProduct = yield product.save()
res.json(newProduct)
} catch (err) {
res.status(400).json(err)
}
})
Model Product.js
const mongoose = require('mongoose')
const Schama = mongoose.Schema
const minlength = [5, 'The value of `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).'];
const ProductSchema = new Schama({
code: { type: String, required: true, minlength, index: true, unique: true, trim: true, lowercase: true },
name: { type: String, required: true, trim: true },
price: { type: Number, required: true, min: 0, max: 100000 },
categories: [String],
})
ProductSchema.path('code').validate(function uniqueEmail(code, fn) {
const Product = mongoose.model('Product')
// Check only when it is a new Product or when code field is modified
if (this.isNew || this.isModified('code')) {
Product.find({ code }).exec((err, products) => {
fn(!err && products.length === 0)
})
} else fn(true)
}, 'Product with given code already exists')
ProductSchema.statics = {
/**
* List products
*
* #param {Object} options
* #api private
*/
pageList: function pageList(conditions, index, size) {
const criteria = conditions || {}
const page = index || 0
const limit = size || 30
return this.find(criteria)
.populate('user', 'name username')
.sort({ createdAt: -1 })
.limit(limit)
.skip(limit * page)
.exec()
},
}
mongoose.model('Product', ProductSchema)
What I expect
I am trying to wrap the error message to make it simple to consumer.
It could be like:
{
"errors": [
{
"message": "Path `price` (-1) is less than minimum allowed value (0).",
"code": "100020"
},
{
"message": "Product with given code already exists",
"code": "100021"
}
],
"success": false
}
The code and the corresponding message will be maintained on api documents. The message is usualy useful for consumer to understand the code and consumer (such as web client) could create their own message such as French messages according to the code and show to end users.
How can I leverage mongoose's valiation to accomplish this? Maybe I could loop erros's properties and combine an code using ${path}-${kind}.
I know that in most case, Client side should do the validation before calling apis. But there must be some cases that errors have to be thrown by APIs.
Any idea for this?

Resources