mongodb validation jsonschema + expressive query failing to insert document - mongodb

So this is kind of a two part question. I have the follow validation schema defined:
db.createCollection(
"users", {
validator: {
$or: [{
company_name: {
$exists: true,
$type: "string"
},
type: {
$in: [
"creator"
],
$exists: true,
$type: "string"
}
},
{
firstname: {
$exists: true,
$type: "string",
},
lastname: {
$exists: true,
$type: "string",
},
type: {
$in: [
"user"
],
$exists: true,
$type: "string"
}
}
],
$jsonSchema: {
bsonType: "object",
required: [
"contacts",
"created",
"email",
"password",
],
properties: {
"contacts": {
bsonType: "array",
items: {
required: [
"email",
"name"
],
properties: {
"email": {
bsonType: "string",
description: "email of the other account"
},
"name": {
bsonType: "string",
description: "a way for the owner to easily identify"
},
}
}
},
"created": {
bsonType: "date",
description: "the date this account was created"
},
"email": {
bsonType: "string",
description: "owner's registered email"
},
"password": {
bsonType: "string",
description: "a hashed password"
},
"reset_code": {
bsonType: "string",
description: "part of the getter link to reset password"
},
}
}
}
}
)
and I'm trying to insert:
db.users.insert({
email: "sadf",
password: "asdf",
created: Date.now(),
contacts: [],
type: "user",
firstname: "test",
lastname: "test"
})
but it's giving me "Document failed validation"`

Problem turned out to be created with the date format. Instead of Date.now() I need to use new Date() or new ISODate()

Related

MongoDB schema validation - sub schemas with oneOf or $or

I have the next validation schema
use("bio_db_schema")
For Biology
const biologyChapterSchema = {
bsonType: "object",
additionalProperties: false,
properties: {
"chapter_name": {enum: ["Biologia"]},
"taxonomias": {
bsonType: ["array"],
items: {
bsonType: "object",
// required: ["taxonomia_name"],
additionalProperties: false,
properties: {
"valor": {bsonType: "string"},
"taxonomia_name": {bsonType: "string"},
"taxonomia_id": {bsonType: "objectId"},
"associates": {
bsonType: ["array"],
items: {
bsonType: "object",
additionalProperties: false,
properties: {
"associate_name": {bsonType: "string"},
"associate_role": {bsonType: "string"},
"associate_id": {bsonType: "objectId"},
},
},
},
},
},
},
}
};
For Physics (just for test, i change the "valor" from "string" to "double")
const physicsChapterValidation = {
bsonType: "object",
properties: {
"chapter_name": {enum: ["Fisica"]},
"estaciones": {
bsonType: ["array"],
items: {
bsonType: "object",
// required: ["taxonomia_name"],
additionalProperties: false,
properties: {
"valor": {bsonType: "double"},
"estacion_name": {bsonType: "string"},
"estacion_id": {bsonType: "objectId"},
"associates": {
bsonType: ["array"],
items: {
bsonType: "object",
additionalProperties: false,
properties: {
"associate_name": {bsonType: "string"},
"associate_role": {bsonType: "string"},
"associate_id": {bsonType: "objectId"},
},
},
},
},
},
},
}
};
Schema
db.createCollection("projects", {
validator: {
$jsonSchema:{
bsonType: "object",
// title: "",
// required: ["chapter_name"],
additionalProperties: false,
properties: {
"_id": {bsonType: "objectId"},
"project_name": {bsonType: "string"},
"sub_projects": {
bsonType: ["array"],
items: {
bsonType: "object",
additionalProperties: false,
properties: {
"sub_project_name": {bsonType: "string"},
"IGA": {bsonType: "string"},
"sub_project_stage": {
bsonType: ["array"],
items: {
bsonType: "object",
additionalProperties: false,
properties:{
"sub_project_stage_name": {bsonType: "string"},
"chapters": {
bsonType: ["array"],
items: {
oneOf: [
biologyChapterSchema,
physicsChapterValidation
]
}
}
},
},
},
},
},
},
},
},
},
});
What i expect:
When i insert a document with:
"chapter_name" = "Biologia", it must use the Schema "biologyChapterSchema" (where "valor" is a "string")
"chapter_name" = "Fisica", it must use the Schema "physicsChapterValidation" (where "valor" is a "double")
i use "oneOf" for it,
works for "Biologia", only accept a string, but when i change to "Fisica" it allows "strins", "integers" and allow another properties like "valor2".
I use VSCode extensión and said $or operator doesnt work for $jsonSchema
Those are just a test for my app, I need that they are in variables to make it readable and to be able to keep it over time and add more sub schemas.
Any tips?
For test:
db.projects.insertOne({
"project_name": "Proyecto Fisica",
"sub_projects": [
{
"sub_project_name": "Subproyecto Fisica",
"IGA": "IGA Fisica",
"sub_project_stage": [
{
"sub_project_stage_name": "Etapa Fisica",
"chapters": [
{
"chapter_name": "Fisica",
"taxonomias": [
{
"taxonomia_name": "Taxonomía Fisica",
"taxonomia_id": ObjectId("123456789235"),
"associates": [
{
"associate_name": "Asociado Fisica",
"associate_role": "Rol Biología",
"associate_id": ObjectId("123456789232")
}
],
"valor": "asdasd"
}
]
}
]
}
]
}
]
})
You are missing additionalProperties in physicsChapterValidation.
const physicsChapterValidation = {
bsonType: "object",
additionalProperties: false,
properties: {
"chapter_name": {enum: ["Fisica"]},

How to get data from relation's with data stored in array's of Id

I have a model batches which has data as
"id": {
"type": "string",
"id": true,
"defaultFn": "uuidv4"
},
"batchType": {
"type": "string",
"required": true,
"default": "COURSE"
},
"venue": {
"type": "string",
"required": true
},
and another Model say bookedBathes
"batchesId": {
"type": [
"string"
],
"required": true
},
and created a relations from batches model to bookedBatches model as
"relations": {
"bookedBatches": {
"type": "referencesMany",
"model": "bookedBatches",
"foreignKey": "batchesId",
"primaryKey": "id"
}
}
now I want all the batches with booked details that are stored as array's of Id in booked details from batch model
let reqObject = {
"where": {
"and": [{
userId: userId,
isActive: true
}]
},
"order": "createdAt DESC",
include: [
{{
relation:"bookedBatches"}}]
}
Batches.find(reqObject, (resError, resData) => {
if (resError) {
return cb(new HttpErrors.BadRequest(resError, {
expose: false
}))
}
return cb(null, resData);
})
But I am not getting any value can any one help to get the values through relation's
Thank You!
i have improved your code. Please try this
let reqObject = {
"where": {
"and": [{
userId: userId,
isActive: true
}]
},
"order": "createdAt DESC",
include: [
{
relation: "bookedBatches",
scope: { fields: ["id","batchesId"] }
}
]
}
Batches.find(reqObject, (resError, resData) => {
if (resError) {
return cb(new HttpErrors.BadRequest(resError, {
expose: false
}))
}
return cb(null, resData);
})

trying to insert document into my collection, but i m getting "errmsg" : "Document failed validation", code: "121"

i am learning MongoDB, I have created a collection and now when i am trying to insert document its showing "errmsg" : "Document failed validation", code: "121"
Following is my collection code:
db.createCollection( "personprofiles", {
validator: { $jsonSchema: {
bsonType: "object",
required: [ "PersonID", "PersonName", "Gender", "DOB", "Occupation", "Noofchildren", "ProfileType", "Purge" ],
properties: {
PersonID: {
bsonType: "number",
description: "must be an integer and is required"
},
PersonName: {
bsonType: "string",
description: "must be an string and is required"
},
Gender: {
enum: [ "Male", "Female" ],
description: "can only be one of the enum values"
},
MartialStatus: {
enum: [ "Single", "Married" ],
description: "can only be one of the enum values"
},
DOB : {
bsonType: "date",
description: "must be an date and is required"
},
Occupation: {
bsonType: "string",
description: "must be an string and is required"
},
Noofchildren: {
bsonType: "number",
description: "must be an integer and is required"
},
ProfileType: {
enum: [ "Gymnast", "Judge", "CompetitionDirector", "Organizers", "Coach", "Administrator", "Volunteers" ],
description: "can only be one of the enum values"
},
Purge: {
enum: [ "Yes", "No" ],
description: "can only be one of the enum values"
},
Addresses: {
bsonType: "array",
description: "must be an array and is required",
required: [ "AddressID", "AddressType", "AddressLine1", "AddressLine2", "Area", "Locality","City","State","Country","PostalCode"],
properties: {
AddressID: {
bsonType: "number",
description: "must be an integer and is required"
},
AddressType: {
enum: [ "Permanent", "Temporary", "Correspondence", "Office" ],
description: "can only be one of the enum values"
},
AddressLine1: {
bsonType: "string",
description: "must be an string and is required"
},
AddressLine2: {
bsonType: "string",
description: "must be an string and is required"
},
Area: {
bsonType: "string",
description: "must be an string and is required"
},
Locality: {
bsonType: "string",
description: "must be an string and is required"
},
City: {
bsonType: "string",
description: "must be an string and isrequired"
},
State: {
bsonType: "string",
description: "must be an string and is required"
},
Country: {
bsonType: "string",
description: "must be an string and is required"
},
PostalCode: {
bsonType: "string",
description: "must be an string and is required"
}
}
},
ContactNumbers: {
bsonType: "array",
description: "must be an array and is required",
required:[ "ContactID", "ContactType"],
properties: {
ContactID: {
bsonType: "number",
description: "must be an integer and is required"
},
ContactType: {
enum: [ "Home", "Mobile", "Office", "CareOf", "Emergency" ],
description: "can only be one of the enum values and is required"
},
ContactNumber: {
bsonType: "object",
description: "must be an string and is required",
required: ["CountryCode", "RegionCode", "PhoneNumber"],
properties:{
CountryCode: {
bsonType: "string",
pattern: "^[+0-9]{2,4}$",
description: "must be an string and is required"
},
RegionCode: {
bsonType: "string",
pattern: "^[0-9]{3}$",
description: "must be an string and is required"
},
PhoneNumber:
{
bsonType: "string",
pattern: "^[0-9]{10}$",
description: "must be an string and is required"
}
}
}
}
},
Email:{
bsonType: "array",
description:"must be an array and is required",
required:["EmailID", "EmailType"],
properties:{
EmailID: {
bsonType: "number",
description:"must be an integer and is required"
},
EmailType:{
bsonType: "string",
pattern : "^([a-zA-Z0-9_\\-\\.]+)#([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$",
description: "must be a string and match regular expression pattern"
}
}
}
}
} }
} )
This is the document i am trying to insert
db.personprofiles.insert({
"PersonID": 1001,
"PersonName": "john simon",
"Gender": "Male",
"MartialStatus": "Single",
"DOB": "1997-8-1",
"Occupation": "Service",
"Noofchildren": 0,
"ProfileType": "Administrator",
"Purge": "yes",
"Addresses":[{
"AddressID": 1,
"AddressType":"Permanent",
"AddressLine1": "101/4",
"AddressLine2":"sundar nagar",
"Area": "kalina",
"Locality": "Santacruz(east)",
"City": "Mumbai",
"State": "Maharashtra",
"Country": "India",
"PostalCode": "400055"
}],
"ContactNumbers": [{
"ContactID":1,
"ContactType":"Home",
"ContactNumber":{
"CountryCode": "+91",
"RegionCode": "022",
"PhoneNumber": "700383555"
}
}],
Email:[{
EmailID: 1,
EmailType: "johnxyz#gmail.com"
}]
})
collection has been created successfully, the only issue i am having to insert a document. Unable to figure out error.
Someone can help me? Look like i forget something.

How do return the count of a particular field in psql db

I have a database tables with the relationships as below.
Cagetory ---> CategorItems //One to many(CategoryItem has categoryId colum)
CatgeoryItems ---> Post // One to many(Post has categoryItemId).
I want to count the total number of records in Post groupBy the categoryItemId also returning along the categoryItem name, and the categoryName. I want columns like returned
CategoryName, item, totalInPostTable
I am using sequelize rdb mapper. When i use the query below
models.Post.findAll({
include: [{
model: models.CategoryItem,
attributes: ['item'],
required: true,
include: [{
model: models.Category,
attributes: ['name'],
required: true,
group: ["name"]
}]
}],
attributes: ['categoryItemId'],
})
It returns the record below
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 2,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 4,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
}
However,it failed and return null without error as soon as i groupBy the categpryItem id like below.
models.Post.findAll({
include: [{
model: models.CategoryItem,
attributes: ['item', [sequelize.fn('COUNT', sequelize.col('id')), 'no_category']],
required: true,
include: [{
model: models.Category,
attributes: ['name'],
required: true,
}]
}],
attributes: ['categoryItemId'],
group: ["categoryItemId"]
})
Pls what am i doing wrong ? ANy help would be appreciated.

sails js many to many associations not working

User.js
module.exports = {
tableName: 'user',
attributes: {
firstName: {
type: 'string',
},
lastName: {
type: 'string',
},
id: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
pets: { //integer
collection:'pet',
via:'owners'
}
}
};
================================
Pet.js
------
module.exports = {
tableName: 'pet',
attributes: {
id: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
breed: {
type: 'string',
},
type: {
type: 'string',
},
name: {
type: 'string',
},
owners: { //integer
collection:'user',
via:'pets'
}
}
};
But when i hit the blueprint api http://localhost:1337/user or http://localhost:1337/pet i dont get associated records
Here is the output in ARC or postman for user and pet
[
{
"pets": [],
"firstName": "a",
"lastName": "aa",
"id": 1
},
{
"pets": [],
"firstName": "b",
"lastName": "bb",
"id": 2
},
{
"pets": [],
"firstName": "c",
"lastName": "cc",
"id": 3
},
{
"pets": [],
"firstName": "d",
"lastName": "dd",
"id": 4
},
{
"pets": [],
"firstName": "e",
"lastName": "ee",
"id": 5
}
],
[
{
"owners": [],
"id": 1,
"breed": "dalmatian",
"type": "male",
"name": "tom"
},
{
"owners": [],
"id": 2,
"breed": "labrador",
"type": "female",
"name": "kg"
},
{
"owners": [],
"id": 3,
"breed": "doberman",
"type": "male",
"name": "tq"
},
{
"owners": [],
"id": 4,
"breed": "puppy",
"type": "male",
"name": "yu"
}
]
One to many association works fine but don't know what am i missing in many to many ?
i tried removing the id column from both the models but that didn't help
Try to add a pet to an owner with the add Blueprint API:
POST /:model/:id/:association/:fk
example :
http://localhost:1337/user/1/pets/2
This will add the pet with id 2 to the owner with id 1.