Define an array of objects, each object is a predefined schema - mongodb

I have two schemas: Category, and User
Category schema is defined as follows:
title: {
type: String,
required: [true, 'Title field is required'],
unique: true
},
type: {
type: String,
required: [true, 'Type field is required'],
}
User schema
email: {
type: String,
required: true
},
isActive: {
type: Boolean,
default: true,
select: false,
},
categories: [{ /* Category schema object */}],
What I'm trying to implement is when ever a user registers, the categories array must be required, and each object within it must match and follow the predefined category schema and have an objectID.
How to do that with Mongoose?

Import the Category schema into the file where you have defined the User schema, then simply specify the type as array, like this:
const Category = require(....);
.
.
.
.
categories: [{
type: Category,
ref: "Category"
]

Related

Mongoose indexing sub-array compoent

I'm trying to indexing one of my subarray component.
My mongoose schema is like that :
mongoose.Schema({
id: {
type: String,
default: uuidv4,
},
organization: {
type: String,
required: true,
},
names: [
{
name: {
type: String,
required: true,
},
language: {
type: String,
required: true,
enum: languages,
},
},
],
}
And If i create the index for organization like that :
schema.index({ organization: 'text' })
But what I want is to index the name inside the names array so I tried:
schema.index({ 'names.name': 'text' })
And here the index is not created, do you have an idea why ?

How to give iDs to dynamic fields in React-Redux?

I created a simple dynamic fields in React-Redux with a plus button to add as many field as I want (hobbies) of an already existing form. I'm using mongodb as a database and so I have this error that tells me that my fields/data don't have iDs.
so how can I generate iDs for my data?
this below is my model with featherJs. as you can see this is how I added my hobbies array in the existing model called myService. I can see that my hobbies are created in mongo (using Robo 3T) which is great but i'm having difficulty reusing them (hobbies) in an other component in Redux. I'm not sure if I should give IDs to this fields or create a new service just for them. I never coded something in backend so I'm confused. what's the rule for this kind of situations.
Any other suggestions would be helpful.
warning in Redux: Each child in a list should have a unique "key" prop.
error in api : Cast to ObjectId failed for value at path "_id" for model "
const { Schema } = mongooseClient;
const myService = new Schema({
type: { type: String, enum: VALID_TYPES, required: true },
user: {
type: mongooseClient.Schema.Types.ObjectId,
ref: 'user',
required: true
},
comment: String,
hobbies: [{
type: mongooseClient.Schema.Types.ObjectId,
ref: 'hobbies',
default: [],
required: false }],
date: {
begin: { type: Date, default: Date.now },
current: { type: Date, default: Date.now },
end: { type: Date, required: true },
},
}, {
timestamps: true
});
return mongooseClient.model('myService', myService);
};

Populate without _id

I have 2 mongoose schemas, one for stock (info about stock) and one for trade. Where trade represents the trades of a stock (so time, volume, etc). Each stock has a symbol code and the data feed that I get the trades from includes the symbol codes as strings. How would I populate these two collections since I can't use the regular mongoose 'ref' here.
Here are my two schemas:
const stockSchema = new Schema({
symbolCode: { type: String, trim: true },
symbol: { type: String, trim: true },
type: { type: String, index: true, trim: true },
country: { type: String, lowercase: true }
})
const tradeSchema = new Schema({
symbolCode: { type: String, index: true },
symbol: { type: String, index: true },
price: Number,
volume: Number,
time: Date,
currency: { type: String, default: 'USD', uppercase: true, index: true }
})
I want to remove the first two fields in the trade schema so that I can just have some kind of reference to the stock here. How can I do this?
use the populate like this:
MyModel.populate([{ path: 'author', select: 'username name -_id' }]);
the -fieldName or in your case -_id will deduct it from the projection.
For future reference, I solved this using populate virtuals as follows:
stockSchema.virtual('trades', {
ref: 'Trade',
localField: 'symbolCode',
foreignField: 'symbolCode',
justOne: true
})

Moongose - how to customize a field in a scheme ? string and array in the same field

I would like to know how I can customize a field where you can use an array and string
eg:
var PostingSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
required: true,
trim: true
},
images: Array,
categorie: Array,
ubication:[{ type: Number, ref: 'Place'}],
agg:[{
agg :{ type: String, ref: 'Agg' },
value : String,
make :[{ type: Number, ref: 'Make'}]
}]
});
In the field agg value, I have a problem that can sometimes be of type string and sometimes can be of type array , should be of the array type I populate it with another scheme. How can I do that?
I made a field called "value ->string" and a "make->array" to do if there is a better way?

Mongoose document schema and validation

I Have a schema like so:
class Schemas
constructor: ->
#mongoose = require 'mongoose'
#schema = #mongoose.Schema
#EmployeeSchema = new #schema
'firstname': { type: String, required: true },
'lastname': { type: String, required: true },
'email': { type: String, required: true, index: { unique: true }, validate: /\b[a-zA-Z0-9._%+-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/ },
'departmentId': { type: #schema.ObjectId, required: true }
'enddate': String,
'active': { type: Boolean, default: true }
#EmployeeSchemaModel = #mongoose.model 'employees', #EmployeeSchema
#DepartmentSchema = new #schema
'name': { type: String, required: true, index: { unique: true } }
'employees' : [ #EmployeeSchema ]
#DepartmentSchemaModel = #mongoose.model 'departments', #DepartmentSchema
So that my employees live in an array of employee documents inside a department
I have several department documents that have a number of employee documents stored in the employees array.
I then added a new department but it contained no employees. If I then attempt to add another department without employees, Mongoose produces a Duplicate key error for the employee.email field which is a required field. The employee.email field is required and unique, and it needs to be.
Is there anyway round this?
If you enable Mongoose debug logging with the coffeescript equivalent of mongoose.set('debug', true); you can see what's going on:
DEBUG: Mongoose: employees.ensureIndex({ email: 1 }) { safe: true, background: true, unique: true }
DEBUG: Mongoose: departments.ensureIndex({ name: 1 }) { safe: true, background: true, unique: true }
DEBUG: Mongoose: departments.ensureIndex({ 'employees.email': 1 }) { safe: true, background: true, unique: true }
By embedding the full EmployeeSchema in the employees array of DepartmentSchema (rather than just an ObjectId reference to it), you end up creating unique indexes on both employees.email and department.employees.email.
So when you create a new department without any employees you are 'using up' the undefined email case in the department.employees.email index as far a uniqueness. So when you try and do that a second time that unique value is already taken and you get the Duplicate key error.
The best fix for this is probably to change DepartmentSchema.employees to an array of ObjectId references to employees instead of full objects. Then the index stays in the employees collection where it belongs and you're not duplicating data and creating opportunities for inconsistencies.
Check out these references:
http://docs.mongodb.org/manual/core/indexes/#sparse-indexes
mongoDB/mongoose: unique if not null (specifically JohnnyHK's answer)
The short of it is that since Mongo 1.8, you can define what is called a sparse index, which only kicks in the unique check if the value is not null.
In your case, you would want:
#EmployeeSchema = new #schema
'firstname': { type: String, required: true },
'lastname': { type: String, required: true },
'email': { type: String, required: true, index: { unique: true, sparse: true }, validate: /\b[a-zA-Z0-9._%+-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/ },
'departmentId': { type: #schema.ObjectId, required: true }
'enddate': String,
'active': { type: Boolean, default: true }
Notice the sparse: true added to your index on EmployeeSchema's email attribute.
https://gist.github.com/juanpaco/5124144
It appears that you can't create a unique index on an individual field of a sub-document. Although the db.collection.ensureIndex function in the Mongo shell appears to let you do that, it tests the sub-document as a whole for its uniqueness and not the individual field.
You can create an index on an individual field of a sub-document, you just can't make it unique.