Unable to check whether the value exists inside nested Model in mongoose - node.js

I am creating poll app. My schema definitions are as below
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/pollApp');
var userSchema = new mongoose.Schema({
username: { type: String, required: true},
phonenumber: { type: String, required: true, unique: true}
});
var option = new mongoose.Schema({
title: {type: String, required: true},
votes: { type: Number, default: 0 },
voterList: {type: []}
});
var poll = new mongoose.Schema({
question: { type: String, required: true, unique: true},
options: { type: [option], required: true},
showVoters: {type: Boolean, default: false}
});
mongoose.user = mongoose.model('User', userSchema);
mongoose.poll = mongoose.model('Poll', poll);
module.exports = mongoose;
voterList will contain all the voters name.Before adding vote i want to check whether user has already voted for the poll(need to check user exists in each voterList array). How to accomplish this?

If you want unique values in the voterList array, you can use $addToSet for pushing a user in the voterList.
but if you want to do some kind of validation. It is better you do a get query which checks if user is already present in the array.
if yes, throw a message saying user already voted else add the user to voterlist
For checking an user is already present in voterList array, it is very simple actually.
You can use a find query like below:
find({voterList:'585ce839c84f5d3d1ef15d56'})
Even if voterList is an array, mongo will see if the provided value is present in the array or not.

Related

mongoose fetch posts by user and by his followings

How to fetch posts by user and all his followings posts (Mongodb, Mongoose, Nodejs)
User Schema
const userSchema = new mongoose.Schema({
firstName: { type: String, required: true, trim: true },
lastName: { type: String, required: true, trim: true },
});
userSchema.set('timestamps', true);
export default mongoose.model('user', userSchema);
Followers Schema
const followSchema = new mongoose.Schema({
follower: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
following: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
status: { type: Boolean, default: true }
});
followSchema.set('timestamps', true);
export default mongoose.model('follow', followSchema);
Posts Schema
const postSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
contents: { type: String, trim: true },
photo: { type: String }
});
postSchema.set('timestamps', true);
export default mongoose.model('post', postSchema);
Thank you in advance! :)
Hy Alamghir its happy to see you here and sorry that you still did not get the answer what i can suggest you after seeing your schema that i think there is no need to create three collections you only need 2 schema first one
const userSchema = new mongoose.Schema({
firstName: { type: String, required: true, trim: true },
lastName: { type: String, required: true, trim: true },
followers:[]
});
userSchema.set('timestamps', true);
export default mongoose.model('user', userSchema);
Now in followers array just push the ids of users who followed this user Now it would be very easy for you to get posts done by these people like this let suppose you have user data in userData variable now you can do this
db.postSchema.find($or:[{userId:userData._id},{userId:$in:userData.followers}])
Sorry, got your question wrong.
There might be a better solution but what you should be able to do is this:
(this gets the posts of the people that are following your original user. If you did mean it the other way around, just switch :) )
// get the user's posts:
var theUserPosts = await postSchema.find({userId: userData._id}).exec();
// get the follower-IDs:
var theFollowersIDs = await followSchema.find({follower: userData._id, status: true}, 'following').exec();
// get the posts of those followers:
var followerPosts = await postSchema.find({userId: {$in: theFollowersIDs}}).exec();
Can you try this and tell us if this works for you?

Mongoose subdocument validation based on required

TL;DR: how to make custom-type field required in one case (and run validations for subdocument) and not required in other case (without validation for subdocument)?
I have an adress schema and models who using this schema (code below).
In one case it is required and in other case it is not. So how to correctly validate an address? All fields except 'apartment' should be required if this field is required and could be empty or valid (for index case) if it's not required.
Is there some options to pass some options to the child schema for this cases or should I make custom validator in each model?
// adress SCHEMA
module.exports = mongoose.Schema({
town: String,
index: {
type: String,
validate: {
validator: function (v) {
return /^\d+$/.test(v)
},
message: 'Invalid index'
}
},
district: String,
street: String,
house: String,
apartment: String
})
// user.js
const Address = require('./address')
const mongoose = require('mongoose')
const userSchema = mongoose.Schema({
address: {
type: Address,
required: true // Adress required here
}
})
module.exports = mongoose.model('User', userSchema)
// other.js
const Address = require('./address')
const mongoose = require('mongoose')
const otherSchema = mongoose.Schema({
address: Address // but not here
})
module.exports = mongoose.model('Other', otherSchema)
to make all fields except apartment required, you just use the required attribute, same way you did with address:
town: {type: String, required: true},
district: {type: String, required: true},
street: {type: String, required: true},
house: {type: String, required: true},
apartment: String
If one of the required fields is left empty, there will be an error when using the create method, the error can be handled to return/keep the user to/on the form page and display an error message to inform them they need to fill the required fields
As for validation, you can check this page of the official mongoose docs to see if the Built-In Validators are enough for your purposes or if you do need to use Custom Validators on some of your fields.

Newly entered field does not inserted in already created collection after updating mongoose schema

I have already created one MongoDB collection using mongoose schema from express web service after some days I found a requirement of a new field in mongoose table so added that field in mongoose schema and try to insert a value of newly added field along with existing fields but it's not get inserted in the newly added document.
So what I have done as a troubleshooting process, I deleted my existing collection totally and then inserted my new document in a collection, Then I found It started working properly. My newly inserted field get inserted into the collection. So Is there any other way to add a new field in MongoDB using mongoose without deleting the whole collection.
My existing user collection schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
var User = mongoose.model('User', userSchema);
module.exports = User;
When I inserted a new document with username and password In above collection It works fine.
My new user collection schema after adding new field (name):
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
name: String,
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
var User = mongoose.model('User', userSchema);
module.exports = User;
But After updating my user schema When I inserted a new document with name, username and password In above collection only insert username and password, name field does not get inserted.
Just do one simple step, add default values to every field you create.
Example
var userSchema = new Schema({
name: {type: String , default: ""},
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
Happy Coding
Name should be also be an object in the schema like so
var userSchema = new Schema({
name: {type: String},
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});

Dont know how to populate Mongoose Query

I have a problem with a mongoose population and I don't know what I should do.
I got two schemas:
var userSchema = new userSchema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
mods: [{ type: mongoose.Schema.Types.ObjectId, ref: 'users'}]
});
var dataSchema = mongoose.Schema({
title: { type: String, required: true, unique: true },
description: { type: String, required: true },
owner: {type: mongoose.Schema.Types.ObjectId, required: true}
});
So one user can have several data packages.
Some users are moderated by other users.
Whats the query for a moderator, that all his own data packages and the ones of the users he is moderating are listed?
You see that I have a SQL background and there's definitely another way to do it with MongoDB.
Thanks for your help!
I'm not clear understand what queries do you need but first you need set ref property in 'owner' field in dataSchema. As about population it's look like this:
//if you use callback
users.find({/*your query*/}).populate('mods')
.exec((err, result)=>{/*your code*/});
//if you use promise
users.find({/*your query*/}).populate('mods').exec()
.then(result=>{/*your code*/})
.catch(err=>{throw err});

Mongoose result.toObject keep Schema methods

Because I cannot edit properties of a non-lean mongoose result, I've used the result.toObject() statement, but that also means I cannot use the methods defined on my Schema.
Example
// Defining the schema and document methods
const User = new Schema({
email: {type: String, required: true, unique: true},
firstname: {type: String, required: true},
registration_date: {type: Date, default: Date.now, required: true},
insert: {type: String},
lastname: {type: String, required: true}
});
User.methods.whatIsYourFirstName = function () {
return `Hello, my firstname is:${this.firstname}`;
};
After a find:
user = user.toObject();
user.registration_date = moment(user.registration_date);
user.whatIsYourFirstName();
// result in "user.whatIsYourFirstName is not a function"
Is this solvable?
Methods and Models are part of Mongoose, not MongoDB.
Whenever you are calling .toObject() you are being returned an object which is ready for storage in MongoDB.
If you do need to do any sort of value transformation, I'd do it just before you deliver the value to the user. Being a time formatting, if you are building an API, I'd do that in the client; if you are working with templates try transforming the value on the same template.

Resources