MongoDB validation part with any one of the field check - mongodb

Trying to figure out how to validate an array of object and map(key, value) pair
{
"commonIdentification": {
"CR": "BR",
"SN": "NAVS87397394"
}
"digitalIdentiifcation": {
"UUID": "326f040b-cf14-4cf9-9e67-57f7ca3ce1b2"
}
}
Here , I want to add the validation like,
In commonIdentification with the presence of CR ,no need for digitalIdentiifcation's presence
In commonIdentification with the absence of CR, digitalIdentiifcation's 'UUID' field is required.
Can anyone please help on reformatting the validation part?I am struggling to validate based on the above points.
{
$jsonSchema: {
properties: {
commonIdentification: {
type: 'object',
required: [
'CR'
],
properties: {
CR: {
type: 'string',
description: 'CR is mandatory '
}
}
}
},
type: 'object',
required: [
'commonIdentification',
'digitalIdentiifcation'
]
}
}

{
$jsonSchema: {
type: 'object',
required: [
'commonIdentification'
],
anyOf: [
{
required: [
'digitalIdentiifcation'
]
},
{
required: [
'commonIdentification'
]
}
],
properties: {
commonIdentification: {
type: 'object',
anyOf: [
{
required: [
'CR'
]
},
{
required: [
'SN'
]
}
],
properties: {
SN: {
type: 'string',
description: 'SN or CR or digitalIdentiifcation is mandatory '
},
CR: {
type: 'string',
description: 'SN or CR or digitalIdentiifcation is mandatory '
}
},
description: 'SN or CR or digitalIdentiifcation is mandatory '
},
digitalIdentiifcation: {
description: 'digitalIdentiifcation'
}
}
}
}

Related

MongoDB: While using triggers, Document fails validation for int type

I am using mongodb triggers for automated update of courses_count in student collection.
My student collection is as:
Validation rule for student collection is defined as:
{
$jsonSchema: {
required: [
'name',
'email',
'password',
'dob',
'address'
],
properties: {
name: {
bsonType: 'string'
},
email: {
bsonType: 'string'
},
password: {
bsonType: 'string'
},
dob: {
bsonType: 'date'
},
address: {
bsonType: 'string'
},
courses_count: {
bsonType: [
'int',
'double',
'decimal'
]
}
courses: {
bsonType: 'array',
items: {
required: [
'_id',
'is_completed',
'is_certified'
],
properties: {
_id: {
bsonType: 'objectId'
},
name: {
bsonType: 'string'
},
is_free: {
bsonType: 'bool'
},
is_completed: {
bsonType: 'bool'
},
is_certified: {
bsonType: 'bool'
},
}
}
}
}
}
}
You can clearly see, I've defined courses_count to be int,doubleordecimal
I have defined courses_count_trigger in mongodb atlas as:
exports = async function(changeEvent) {
const { fullDocument } = changeEvent;
const mongodb = context.services.get("vidly");
const docId = changeEvent.documentKey._id;
var courses_count= 0;
if(fullDocument.courses){
courses_count=fullDocument.courses.length;
}
return mongodb.db("coursera").collection("student").updateOne({_id:docId},{ $set:{courses_count: courses_count}});
}
It's fine when there are some courses in my student collection.
It updates correctly using fullDocument.courses.length.
But when there are no courses , it fails to update the document.
i.e. it fails the validation.
I have also checked:
typeof(fullDocument.courses.length) gives number.
typeof(0) is obviously number.
Why does it fails validation? Please help.

How do you update a nested array with Mongoose?

This is what I have so far. This is my AnswerSchema with a comments array nested within that I am trying to update.
const AnswerSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
question: {
type: Schema.Types.ObjectId,
ref: 'question',
},
text: {
type: String,
required: true,
},
name: {
type: String,
},
avatar: {
type: String,
},
views: {
type: Number,
},
date: {
type: Date,
default: Date.now,
},
answerLikes: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
},
],
comments: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
text: {
type: String,
required: true,
},
name: {
type: String,
},
avatar: {
type: String,
},
commentLikes: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
},
],
date: {
type: Date,
default: Date.now,
},
},
],
})
and here is my update route that I am trying to use to update the comments array text field
try {
const updatedAnswer = await Answer.findOneAndUpdate(
{ _id: req.params.answer_id },
{
$set: { 'comments.$[comment].text': formattedAnswer },
},
{
arrayFilters: [{'comment._id': req.params.comment_id }],
},
{ new: true }
)
res.json(updatedAnswer)
I keep getting the error 'Callback must be a function, got [object Object]' and cant figure out a fix.
Any ideas?
Thanks!
The problem in your code is that you are passing 4 parameters to the findOneAndUpdate function.
The 4th argument is a callback which accepts a function:
(err /* an error if occurred */, doc /* the updated document */) => {}
In order to solve that you need to combine your last 2 arguments into one object like:
{
arrayFilters: [{'comment._id': req.params.comment_id }],
new: true
}
Final query:
const updatedAnswer = await Answer.findOneAndUpdate(
{ _id: req.params.answer_id },
{
$set: { 'comments.$[comment].text': formattedAnswer },
},
{
arrayFilters: [{'comment._id': req.params.comment_id }],
new: true
}
)
The 4th argument in findOneAndUpdate function takes in a callback function that was where your error was.
Try this
try{
const updatedAnswer = await Answer.findOneAndUpdate(
{ _id: req.params.answer_id },
{
$set: { 'comments.$[comment].text': formattedAnswer },
},
{
arrayFilters: [{'comment._id': req.params.comment_id }],
new: true
}
);
res.json(updatedAnswer);
}catch(err){
//console.log(err)
}

MongoDB Only shows ids when I use ref model in another ref model

I use mongoose. I tried to add models in
ProductController.js:
const student = require('../models/studentModel');.populate('student_list')
but I still get the same result.
productModel.js
{
lectureProductId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Lecture',
}
}
lectureModel.js
{
task_list: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'task'
}],
student_list: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'student'
}],
teacher: {
type: mongoose.Schema.Types.ObjectId,
ref: 'teacher', required: true,
},
}
productController.js
productModel.find()
.populate('lectureProductId')
.populate('taskProductId')
.then(product => {
res.json({
status: 'success',
message: 'products retrieved successfully',
data: product
});
})
lectureController.js
lectureModel.find()
.populate('teacher')
.populate('task_list')
.populate('student_list')
.then(lecture => {
res.json({
status: 'success',
message: 'Lectures retrieved successfully',
data: lecture,
});
})
When I send request I see :
"lectureProductId": {
"keywords": [ "MATLAB", "BİSECTİON", "NEWTON-RAHSON" ],
"task_list": [ "5d26d617454d23000665421c", "5d26d617454d230006654217", "5d26d617454d23000665421b", "5d26d617454d23000665421a", "5d26d617454d230006654218" ],
"student_list": [ "5d26d615454d230006654206", "5d26d615454d230006654207", "5d26d615454d230006654208", "5d26d615454d23000665420c", "5d26d615454d23000665420d", "5d26d616454d23000665420e", "5d26d616454d23000665420f" ],
"_id": "5d26d617454d230006654221",
"name": "Numerical Analysis",
"programmingLanguages": "MATLAB",
"description": "MATLAB for easy level",
"teacher": "5d26d616454d230006654215", "__v": 0
}
How can I see student_list with other fields?
"student_list": [
"5d26d615454d230006654206",
"5d26d615454d230006654207",
"5d26d615454d230006654208",
"5d26d615454d23000665420c",
"5d26d615454d23000665420d",
"5d26d616454d23000665420e",
"5d26d616454d23000665420f"
]
productModel
.find()
.populate({
path: 'lectureProductId',
model: 'lecture',
populate: { path: 'task_list' },
})
This is answer for my question.
productModel
.find()
.populate({
path: 'id with ref',
model: 'childs model',
populate: { path: 'id with ref in childs model' },
})

sails update the doc, nothing happen, not err message

eventController:
newHelper: function(req, res) {
const eventID = req.body.eventID;
let newHelper = req.body.newHelper;
newHelper.eventAssoc = eventID;
Wapphelprecords.create(newHelper).exec(function(err, newhelper) {
if (err) {
return res.serverError(err); }
sails.log('add new helper:', newhelper);
return res.json(newhelper);
});
}
when I do this action, the database nothing happen, and no err message, this is model under blow:
WappeventController model:
module.exports = {
attributes: {
eventID: {
type: 'integer',
// autoIncrement: true,
unique: true,
// defaultsTo: 0
},
openid: {
type: 'string',
},
author: {
model: 'wappuserinfo'
},
content: {
type: 'string'
},
allowShare: {
type: 'boolean'
},
imageList: {
type: 'array'
},
money: {
type: 'float',
},
helpers: {
collection: 'wapphelprecords',
via: 'eventAssoc',
},
bestHelper: {
collection: 'wapphelprecords',
via: 'eventAssoc',
}
},
Wapphelprecords Model:
module.exports = {
attributes: {
eventAssoc: {
model: 'wappevents',
},
content: {
type: 'string'
},
contact: {
type: 'string'
},
userInfo: {
model: 'wappuserinfo'
},
bestHelper: {
type: 'boolean'
},
moneyEarn: {
type: 'float'
}
}
};
when I do newHelper action, the database nothing happened, and nothing error notice, I just do not understand. need help, thx.
spend whole day to fix it, and finally:
module.exports = {
attributes: {
eventID: {
type: 'integer',
// autoIncrement: true,
primaryKey: true, //<---- set this primarkey to true
unique: true,
// defaultsTo: 0
},
openid: {
type: 'string',
},
author: {
model: 'wappuserinfo'
},
content: {
type: 'string'
},
allowShare: {
type: 'boolean'
},
imageList: {
type: 'array'
},
money: {
type: 'float',
},
helpers: {
collection: 'wapphelprecords',
via: 'eventAssoc',
},
bestHelper: {
collection: 'wapphelprecords',
via: 'eventAssoc',
}
},

Sails.js attribute type array in waterline mongoDB

I want to create a model like below. users model having attribute agreements of type array.I was not able to find a example in waterline where attributes type is an array of object. Please advise
`
module.exports = {
attributes: {
userName: {
type: "string",
unique: true,
required: true
},
Name: {
type: "string",
required: true,
minLength: 2
},
phone: {
type: "string",
required: true
},
password: {
type: "string",
minLength: 6
},
roles: {
type: "array",
required: true,
enum: ['Admin', 'User']
},
agreements: {
type : "array",
agreement :{
version : "string",
dateSigned :"date",
}
},
`
Use one to many association.
Assume that your model is Model.js
agreements: { collection: 'Agreement', via : 'model' }
Create Agreement.js in models
module.exports: {
attributes: {
model : { model: 'Model' },
version : { type: 'string' },
dateSigned : { type: 'datetime' }
}
}
See this documentation.