On the backend I have two Schemas:
User:
var UserSchema = new mongoose.Schema({
isActive: {type: Boolean, default: false},
isVerified: {type: Boolean, default: false},
firstName: {type: String, required: [true, "can't be blank"]},
lastName: {type: String, required: [true, "can't be blank"]},
email: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/\S+#\S+\.\S+/, 'is invalid'], index: true},
phone: {type: Number, unique: true, required: true, required: [true, "can't be blank"]}, // validate phone
role: {type: String, enum: ['invalid', 'precustomer', 'customer', 'broker', 'brokerAdmin', 'dealer']},
hash: String,
salt: String,
address: {type: Object, required: [isRequired('address'), "can't be blank"]}, //require customer
organization: { type: mongoose.Schema.Types.ObjectId,
ref: 'Organization',
required: [isRequired('organization'), "can't be blank"]}, //require broker && dealer
deliverySchedule: String // for now.. make this custom obj soon --- OPTIONAL
}, {timestamps: true});
Application:
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');
var ApplicationSchema = new mongoose.Schema({
customer: {type: mongoose.Schema.Types.ObjectId, ref: 'User', required: [true, "can't be blank"]},
dealer: {type: mongoose.Schema.Types.ObjectId, ref: 'User', required: [true, "can't be blank"]},
broker: {type: mongoose.Schema.Types.ObjectId, ref: 'User', required: [true, "can't be blank"]},
files: {type: mongoose.Schema.Types.ObjectId, ref: 'Files', required: [true, "can't be blank"]},
}, {timestamps: true});
mongoose.model('Application', ApplicationSchema);
};
On the front end, in order for a "Broker" to create an "Application," he must first add a "customer" to the application. To do this, a Broker will search for a user by email, and the server can respond with either:
email exists (User Object = id, email, ...)
No user found ({})
It would not be possible to store an _id in "Create Application" API endpoint, because when a "Broker" creates an "Application", the "customer" is sent a link in their email to register (new _id), and the _id linked to the Application is lost (as far as I know.) I would like my "customer" "dealer" and "broker" to be String instead of mongoose.Schema.Types.ObjectId, however I would like it to work with .populate('customer dealer broker') using email instead of ID.
Would it make more sense to remove the required validation for name, phone, etc from the User Schema and only require an email for "registration" and request the rest from the "customer" after clicking the confirmation link?
Related
I am building a user model in mongoose, nodesjs where the each user has set of contacts which are actually users, each contact is a user.
I have two approaches
Approach 1
Is to add the contacts as an array of user objects to reference User model in the user model as an array of contacts but i want to determine the Date and time of when was the contact was added, i don't know how to add that
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'Please enter a name'],
},
username: {
type: String,
match: [
/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/,
'Please enter a valid user name',
],
},
password: {
type: String,
required: [true, 'Please enter a password'],
minLength: 6,
select: false,
},
role: {
type: String,
enum: ['user'],
default: 'user',
},
resetPasswordToken: String,
resetPasswordExpire: Date,
allowAutoApproveContacts: {
type: Boolean,
default: false,
},
createdAt: {
type: Date,
default: Date.now,
},
contacts: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
],
});
**Approach 2 **
is to create a new model Contact and reference the user model as user and the User model again as the contact, and add the addedAt Date to determine when was the contact was added and maybe add other properties
const ContactSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: true,
},
contact: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: true,
},
addedAt: {
type: Date,
default: Date.now,
},
autoAllowed: Boolean,
});
Can you please help me with which approach is the correct approach or if you can suggest a new one
Here actually I want to make the service collection that contain the array of references of the ratings. when a user rate a service than an element is pushed in the array containing reference of user , service ID no and the rating.
Service Model like this:
var ServiceSchema = new Schema({
user_id:{
type: String,
required: [true, 'please provide user id']
},
name: {
type: String,
required: [true, 'please enter your name']
},
rating : [{ type: Schema.Types.ObjectId, ref: 'rating' }],
});
Rating schema:
var RatingSchema = Schema({
S_id : { type: Schema.Types.ObjectId},
Rating : Number,
By : { type: Schema.Types.ObjectId}
});
user schema:
var UserSchema = new Schema({
id: {
type: String,
unique: true,
required: [true, 'please enter your id']
},
password: {
type: String,
required: [true, 'please enter your password']
},
name: {
type: String,
required: [true, 'please enter your name']
},
type: {
type: [{
type: String,
enum: ['visitor', 'seller']
}],
default: ['visitor']
},
});
and I have defined the export as:
module.exports = mongoose.model('user', UserSchema, 'users');
module.exports = mongoose.model('service', ServiceSchema, 'service');
module.exports = mongoose.model('rating', RatingSchema, 'rating');
I want to make a function called rate but I am not getting how to make it.
exports.rate = function(req, res) {
var curr_service = new Service(req.body, result);
new_service.save(function(err, service) {
if (err)
res.send(err);
res.json(service);
});
};
So far I have done this.
Can someone help me to understand what should I do now? because I haven't find that much about mongoose to add ref in array...
In my case. This error was happening because instead of putting {es_indexed: true} inside the object declaration, I was putting it in the object that was using. For example:
const Client: Schema({
name: {type: String, es_indexed: true},
address: {type: Adress, es_indexed: true} //Wrong, causing error
})
Adress: Schema({
address: {type: String},
zipCode: {type: Number}
})
The correct way to use, is putting es_indexed: true into primitive types inside "Adress" schema declaration.
const Client: Schema({
name: {type: String, es_indexed: true},
address: {type: Adress} //Right way
})
Adress: Schema({
address: {type: String, es_indexed: true},
zipCode: {type: Number, es_indexed: true}
})
I hope it was helpful
I have the following user schema (where all distinct properties of different user types are consolidated):
var UserSchema = new mongoose.Schema({
status: String,
firstName: String,
lastName: String,
address: Object,
email: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/\S+#\S+\.\S+/, 'is invalid'], index: true},
organization: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Organization' }],
phone: {type: Number, unique: true, required: true, required: [true, "can't be blank"]},
role: String,
hash: String,
salt: String,
deliverySchedule: [{type: String, required: true}]
}
"Common" Schema (what all user types share in common):
var UserSchema = new mongoose.Schema({
status: String,
firstName: String,
lastName: String,
email: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/\S+#\S+\.\S+/, 'is invalid'], index: true},
phone: {type: Number, unique: true, required: true, required: [true, "can't be blank"]},
role: String,
hash: String,
salt: String
}
Role = "Customer":
address: [{type: Object, required: true}]
Role = "DeliveryMan":
deliverySchedule: [{type: String, required: true}]
organization: [{ type: mongoose.Schema.Types.ObjectId, required: true,
ref: 'Organization' }],
Role = "Seller":
organization: [{ type: mongoose.Schema.Types.ObjectId, required: true,
ref: 'Organization' }],
I would like to add (and REQUIRE if possible) some fields to the "common" schema based on the user's role. However, I want to store them in the same collection.
How can I add a method to my models/Users.js to add properties to the schema based on "user.role"
Make require validation optional for each role dependent fields.
var UserSchema = new mongoose.Schema({
status: String,
firstName: String,
lastName: String,
email: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/\S+#\S+\.\S+/, 'is invalid'], index: true},
phone: {type: Number, unique: true, required: true, required: [true, "can't be blank"]},
role: {type: String, enum: ['Customer', 'DeliveryMan', 'Seller'], required: true},
address: {type: [Object], required: isRequired("address")},
deliverySchedule: {type: [String], required: isRequired("deliverySchedule")},
organization: { type: [mongoose.Schema.Types.ObjectId], ref: 'Organization', required: isRequired("organization")},
hash: String,
salt: String
});
function isRequired(field){
return function(){
if(field == "address"){
return this.role === "Customer"
}
else if(field == "deliverySchedule"){
return this.role === "DeliveryMan"
}
else if(field == "organization"){
return this.role === "Seller" || this.role === "DeliveryMan"
}
}
};
I want to display in my user/myarticlesview only articles by logged in user.
How can i do that:
Here is my User model and Article schema:
let userSchema = mongoose.Schema(
{
email: {type: String, required: true, unique: true},
passwordHash: {type: String, required: true},
salt: {type: String, required: true},
articles: [{type: ObjectId, ref: 'Article'}],
roles: [{type: ObjectId, ref: 'Role'}]
}
);
let articleSchema = mongoose.Schema (
{
author: {type: ObjectId, ref: 'User'},
title: {type: String, required: true },
content: {type: String, required: true },
phone: {type: Number, required: true },
date: {type: Date, default: Date.now() }
}
);
I want to do this in my userController and passed it to the view:
myArticlesGet: (req, res) => {
if (!req.isAuthenticated()) {
res.redirect('/');
return;
}
res.render('user/myarticles')
}
I cant figure it out how to make the query.Thank you.
As you are using express sessions you can store userId in the express session when the user is authenticated and then you can get user articles from user like that
User.find({_id: req.session.userId}).populate('articles')
I have 2 models:
Here is the User Model:
const userSchema = new mongoose.Schema({
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
passwordResetToken: String,
passwordResetExpires: Date,
facebook: String,
twitter: String,
tokens: Array,
profile: {
name: String,
gender: String,
location: String,
website: String,
picture: String
}
}, { timestamps: true });
And here is the Revive Model:
const reviveSchema = new mongoose.Schema({
reviveShowName: {type: String, required: true},
reviveTitle: {type: String, required: true},
reviveCategory: {type: String, required: true},
reviveGoal: {type: Number, required: true},
revivePhoto: {type: String, required: true},
reviveVideo: {type: String},
reviveStory: {type: String},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
name: String
}
}, { timestamps: true });
In the Revive model, I'm trying to the reference the author and get the author's id and that works... How do I also get the name from profiles -> name...? Clearly name: String is wrong...
Mongoose relations work, based on the ref and type value of the nested object. In your case you have associated the id property of author to point to the User model.
If you want to populate the author with the user information, you should just do :
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
Then in your query you just use populate
Revive.find({})
.populate( 'author' )
.exec( function( error, docs ) {
console.log( docs ); // will have `[{author:{profile:{...}}}]` data
} );