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

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.

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"]},

Mongodb data schema validation errors

In my flask app I am trying to insert data into a mongodb database and validating the data, but I keep getting validation errors and I can seem to be able to locate why this is the case. I am new to mongodb. Note the validation rules are applied when I create the users collection like this:
try:
collection = d.list_collections()
if collection is not None:
if os.environ.get("FLASK_ENV") == 'development':
d.users.drop()
d.emails.drop()
d.create_collection(name="users", validator=users.user, validationLevel='strict', validationAction='error')
d.create_collection(name="emails", validator=emails.email, validationLevel='strict', validationAction='error')
except OperationFailure as e:
app.logger.error(f'Validation setup error: {e}')
Here is my validation python file (users.py):
user = {
"bsonType": "object",
"additionalProperties": False,
"required": [
"username", "first_name", "last_name",
"password", "email", "pin",
"phone_number", "firebase_uid", "groups",
"created_at"
],
"properties": {
"username": {
"bsonType": "string",
"description": "must be a string and is required"
},
"first_name": {
"bsonType": "string",
"description": "must be a string and is required"
},
"last_name": {
"bsonType": "string",
"description": "must be a string and is required"
},
"password": {
"bsonType": "binData",
"description": "must be a hashed string and is required"
},
"email": {
"bsonType": "string",
"pattern": "^[a-z0-9]+[\\._]?[a-z0-9]+[#]\\w+[.]\\w{2,3}$",
"description": "must be a string and is required"
},
"pin": {
"bsonType": "int",
"description": "must be a number and is required"
},
"phone_number": {
"bsonType": "string",
"pattern": "^\\+234[^0](?:\\d{9})",
"description": "must be a string and is required"
},
"firebase_uid": {
"bsonType": "string",
"description": "User firebase registration uid"
},
"groups": {
"bsonType": "object",
"required": ["owned", "belong"],
"properties": {
"owned": {
"bsonType": "array",
"uniqueItems": True,
"items": {
"grp_id": {
"bsonType": "objectId",
"description": "Must be an objectId"
}
}
},
"belong": {
"bsonType": "array",
"uniqueItems": True,
"items": {
"grp_id": {
"bsonType": "objectId",
"description": "Must be an objectId"
},
}
}
}
},
"created_at": {
"bsonType": "date",
"description": "The date and time user was created"
}
}
}
And this is the data being inserted:
{
"username": "joshua223",
"first_name": "Joy",
"last_name": "Kudosen",
"password": "password",
"email": "joshua22#gmail.com",
"pin": 1245,
"phone_number": "+2348022192256",
"firebase_uid": "XttdyeAOGxewe3434renuRTjCX0KsHXxod92",
"groups": {
"owned": [
],
"belong": [
]
}
}
And this is the error:
[2022-05-19 01:30:28 +0100] [420098] [ERROR] Validation error: Document failed validation, full error: {'index': 0, 'code': 121, 'errInfo': {'failingDocumentId': ObjectId('62858fa4e0decf4b6664dc6e'), 'details': {'operatorName': '$and', 'clausesNotSatisfied': [{'index': 0, 'details': {'operatorName': '$eq', 'specifiedAs': {'bsonType': 'object'}, 'reason': 'field was missing'}}, ...
Please note I am inserting the "created_at" field using a python Datime.now(timezone.utc)" function and it isn't in the original data. This is how I am inserting:
try:
current_app.logger.info("register_user Function called ...")
# Check for duplicate user registration using
# email and phone_number
# print(f'email: {dict(dumps(json_string))}')
if is_valid_data(json_string["email"], mtype="email") \
and is_valid_data(json_string["phone_number"], mtype="phone_number") \
and is_valid_data(json_string["username"], mtype="username"):
if get_user_by_property("email", json_string["email"], confirm=True) \
or get_user_by_property("phone_number", json_string["phone_number"], confirm=True) \
or get_user_by_property("username", json_string["username"], confirm=True):
return False
else:
now = datetime.now(timezone.utc)
print(f"DateTime: {now}") # TODO: Remove
# print(f'Password: {user_info["password"]}')
user_info = {
"username": json_string["username"],
"first_name": json_string["first_name"],
"last_name": json_string["last_name"],
"password": hash_user_input(json_string["password"]),
"email": json_string["email"],
"pin": json_string["pin"],
"phone_number": json_string["phone_number"],
"firebase_uid": json_string["firebase_uid"],
"groups": json_string["groups"],
"created_at": now
}
try:
print("Insert_one about to be called ...") # TODO: Remove
u = db.users.insert_one(user_info).inserted_id
except Exception as i:
return current_app.logger.error(f'Validation error: {i}')

mongodb validation jsonschema + expressive query failing to insert document

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()

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.

Mongo DB group records and return selected fields

I want to group the documents on the basis of a specific value. Also I need the selected keys in return.
Here is my document:
{
title: "Add 1",
userId: 1,
description: "this is add 1",
location: {
city: "Newyork",
address: "Street 1, Flat # 40"
},
createdAt: "2015-10-20",
title: "Add 2",
userId: 1,
description: "this is add 2",
location: {
city: "Paris",
address: "Street 2, Flat # 80"
},
createdAt: "2015-10-22",
title: "Add 3",
userId: 1,
description: "this is add 3",
location: {
city: "Newyork",
address: "Street 5, Flat # 58"
},
createdAt: "2015-10-23"
}
I want to group the documents by location.city. Also I need only title and location in return.
What should be the query for above scenario?
I have tried this query:
Adds.aggregate([
{ $match: { userId: params.userId } },
{ $group: { _id: "$location.city" } },
]);
The above query only returns location.city, I want complete object of location & title.
Assuming that your data actually looks like this:
[
{
title: "Add 1",
description: "this is add 1",
location: {
city: "Newyork",
address: "Street 1, Flat # 40"
},
createdAt: "2015-10-20",
},
{
title: "Add 2",
description: "this is add 2",
location: {
city: "Paris",
address: "Street 2, Flat # 80"
},
createdAt: "2015-10-22",
},
{
title: "Add 3",
description: "this is add 3",
location: {
city: "Newyork",
address: "Street 5, Flat # 58"
},
createdAt: "2015-10-23"
}
]
You could use an aggregate query such as:
db.adds.aggregate([
{ $group :
{
_id : "$location.city",
data : { $push : { "title" : "$title", "location" : "$location" } }
}
}
]);
userId is missing in your documents, if your collection looks like this your aggregate function is correct.
{
"title": "Add 1",
"userId": 1,
"description": "this is add 1",
"location": {
"city": "Newyork",
"address": "Street 1, Flat # 40"
},
"createdAt": "2015-10-20"
},
{
"title": "Add 2",
"userId": 2
"description": "this is add 2",
"location": {
"city": "Paris",
"address": "Street 2, Flat # 80"
},
"createdAt": "2015-10-22"
},
{
"title": "Add 3",
"userId": 1,
"description": "this is add 3",
"location": {
"city": "Newyork",
"address": "Street 5, Flat # 58"
},
"createdAt": "2015-10-23"
}
Test using Mongodb's console
db.Adds.aggregate([
{ $match: { userId: 1 } },
{ $group: { _id: "$location.city" } }
]);
Adding title to your results
db.Adds.aggregate([
{ $match: { userId: 1 } },
{
$group: {
_id: "$location.city",
title: {$push: "$title"}
}
}
]);