How to request for "like" for the function "populate" - javascript

I would like to retrieve with a search field the channels according to the user's first name.
const UserSchema = new mongoose.Schema({
email: {
type: String,
require: true,
trim: true,
unique: true
},
password: {
type: String,
require: true,
trim: true,
unique: true
},
_profile: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Profile',
require: true,
unique: true
}
})
const ProfileSchema = new mongoose.Schema({
name: {
type: String,
require: true,
trim: true,
unique: true
},
firstname: {
type: String,
require: true,
trim: true,
unique: true
}
})
const ChannelSchema = new mongoose.Schema({
title: {
type: String,
require: true,
trim: true,
unique: true
},
_user: {
type: String,
require: true,
trim: true,
unique: true
}
})
const User = mongoose.model('User', UserSchema)
const Profile = mongoose.model('Profile', ProfileSchema)
const Channel = mongoose.model('Channel', ChannelSchema)
I used to populate function to retrieve the data from the joins
let ChannelSearch = await Channel
.find()
.populate({
path: '_user',
select:'-password',
populate: {
path: '_profile'
}
})
but where I block is how to retrieve the channels based on the user's first name
I can't seem to find how it is possible to make a like request through the populate function
Thank you in advance for your help !! =)

you can your regex to find your data.
let ChannelSearch = await Channel
.find({firstname: /regex/})
.populate({
path: '_user',
select:'-password',
populate: {
path: '_profile'
}
})
or use $regex in yout mongo query.
https://docs.mongodb.com/manual/reference/operator/query/regex/

I believe this is not possible, in the mongoose documentation it is put this:
In general, there is no way to make populate() filter stories based on properties of the story's author. For example, the below query won't return any results, even though author is populated.
const story = await Story.
findOne({ 'author.name': 'Ian Fleming' }).
populate('author').
exec();
story; // null
If you want to filter stories by their author's name, you should use denormalization.

Related

Mongoose find.where in a schema with an attribute of type ObjectId

I have this schemas:
UserLike
const UserLikeSchema = Schema({
user: {
type: Schema.Types.ObjectId,
ref: "User",
required: [true, "User is required"],
},
game: {
type: Schema.Types.ObjectId,
ref: "Game",
required: [true, "Game is required"],
}
});
Game
const GameSchema = Schema({
title: {
type: String,
required: [true, "Title is required"],
},
status: {
type: Boolean,
default: true,
},
});
I need to find all UserLikes where populated Game.status are true
I'm trying with a code like this
const games = await UserLike.find()
.populate("game")
.where("game.status")
.equals(true);
But I can't find a solution :(
You should try using the match option as directed by mongoose docs.
https://mongoosejs.com/docs/populate.html#query-conditions
The query might look something like this:
UserLike.
find().
populate({
path: 'game',
match: { status: true },
}).
exec();

Mongoose Exclude document results at schema level

I am creating a model for my users. Each user has a property isVerified which is a boolean. I want to be able to call Model.find on the mongoose model and exclude all documents with isVerified === false without having to specify this during the query.
I want to set it in the schema such that whenever Model.find is called those documents are automatically excluded. Any help is appreciated
User model:
const UserSchema:Schema = new Schema({
name: {
type: String,
required: true,
trim: true,
},
email: {
type: String,
required: true,
unique: true,
lowercase: true,
trim: true,
index: true,
validate: {
validator: (value:string) => validator.isEmail(value),
message: (props:any) => "Invalid Email Address"
},
},
password: {
type: String,
trim: true,
required: true,
select: false,
minlength: 6,
validate: {
validator: (value:string) => !validator.contains(value, "password"),
message: (props:any) => "Your password cannot contain the word 'password'"
}
},
phoneNumber: {
type: String,
trim: true,
required: true,
validate: {
validator: (value:string) => validator.isMobilePhone(value, 'any', {strictMode: true}),
message: (props:any) => "Please include country code (e.g. +233 for Ghana +44 for the United Kingdom) to phone number"
}
},
isActive: {
type: Boolean,
default: false
}
,
tokens: [
{
token: {
type: String,
required: true
}
}
]
},{
strict: "throw",
timestamps: true
})
Edit:
I did some digging around and it appears I can overwrite the base methods to reimplement the query returned. I attempted to this is as seen below :
UserSchema.statics.find = function () {
let query = UserModel.find.apply(this, arguments);
query.where('isActive').ne(false)
return query;
}
However I obtain the following error
RangeError: Maximum call stack size exceeded
Finally figured it out. Needed to apply the change to the Model object and not the instance UserModel as seen below:
UserSchema.statics.find = function () {
let query = Model.find.apply(this, arguments);
query.where('isActive').ne(false)
return query;
}
Now the find method skips inactive users

posts.populate is not a function

I'm trying to populate my post's author fields (which is are object ids) with the corresponding author objects which are in a separate collection.
My controller code is as follows:
exports.readPosts = async (req, res) => {
try {
const posts = await Post.find({ board: req.params.board });
await posts.populate("author").execPopulate();
res.send(posts);
} catch (err) {
res.status(400).send(err.message);
}
};
I'm at a loss as to why this isn't working as I have very similar code in another controller method that is working just fine.
All help greatly appreciated.
Below is the relevant Model file:
const mongoose = require("mongoose");
const postSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
trim: true,
},
content: { type: String, required: true, trim: true },
comments: [
{
comment: {
type: String,
required: true,
trim: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
date: {
type: Date,
default: Date.now(),
},
},
],
author: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
board: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Board",
},
},
{ timestamps: true }
);
const Post = mongoose.model("Post", postSchema);
module.exports = Post;
posts is an array of models. populate must be called on a model. The preferred way to do this is at query time. It probably works on your other controller because you are using a findOne so it is returning the model, not the Array.
const posts = Post
.find({ board: req.params.board })
.populate('author')
.exec();

Mongoose (mongodb) $push data as subdocument, validate unique?

I have a User document which has a Notes subdocument.
I'm using the following code to push new notes for the user with the given email address.
UserSchema.statics.addNotesToUser = function (email, notes, callback) {
return this.updateOne(
{'email': email},
{$push: {notes}},
callback
)
};
This is working fine, however it's ignoring my unique constraint on the NoteSchema. these are my schemas
const NoteSchema = new Schema({
_id: false,
id: {type: String, required: true, trim: true, unique: true},
content: {type: String, required: true, trim: true, lowercase: true},
added: {type: Date, default: Date.now},
used: {type: Date, default: Date.now},
book: {
name: {type: String, required: true}
}
});
const UserSchema = new Schema({
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [NoteSchema]
});
I'm wondering how I can make sure that when pushing new notes to my user, I can validate if the ID of the notes is unique.
Thank you.
To achieve uniqueness constraint like functionality in subdocuments, hope that's OK.
let notesId = [];
notes.forEach(function(val,index){
notesId.push(val.id)
})
db.yourCollection.update(
{ 'email': email, 'NoteSchema.id': { '$ne': { $each: notesId } }},
{$push: {notes} },
callback)

How To Create Mongoose Schema with Array of Object IDs?

I have defined a mongoose user schema:
var userSchema = mongoose.Schema({
email: { type: String, required: true, unique: true},
password: { type: String, required: true},
name: {
first: { type: String, required: true, trim: true},
last: { type: String, required: true, trim: true}
},
phone: Number,
lists: [listSchema],
friends: [mongoose.Types.ObjectId],
accessToken: { type: String } // Used for Remember Me
});
var listSchema = new mongoose.Schema({
name: String,
description: String,
contents: [contentSchema],
created: {type: Date, default:Date.now}
});
var contentSchema = new mongoose.Schema({
name: String,
quantity: String,
complete: Boolean
});
exports.User = mongoose.model('User', userSchema);
the friends parameter is defined as an array of Object IDs.
So in other words, a user will have an array containing the IDs of other users. I am not sure if this is the proper notation for doing this.
I am trying to push a new Friend to the friend array of the current user:
user = req.user;
console.log("adding friend to db");
models.User.findOne({'email': req.params.email}, '_id', function(err, newFriend){
models.User.findOne({'_id': user._id}, function(err, user){
if (err) { return next(err); }
user.friends.push(newFriend);
});
});
however this gives me the following error:
TypeError: Object 531975a04179b4200064daf0 has no method 'cast'
If you want to use Mongoose populate feature, you should do:
var userSchema = mongoose.Schema({
email: { type: String, required: true, unique: true},
password: { type: String, required: true},
name: {
first: { type: String, required: true, trim: true},
last: { type: String, required: true, trim: true}
},
phone: Number,
lists: [listSchema],
friends: [{ type : ObjectId, ref: 'User' }],
accessToken: { type: String } // Used for Remember Me
});
exports.User = mongoose.model('User', userSchema);
This way you can do this query:
var User = schemas.User;
User
.find()
.populate('friends')
.exec(...)
You'll see that each User will have an array of Users (this user's friends).
And the correct way to insert is like Gabor said:
user.friends.push(newFriend._id);
I'm new to Mongoose myself, so I'm not entirely sure this is right. However, you appear to have written:
friends: [mongoose.Types.ObjectId],
I believe the property you're looking for is actually found here:
friends: [mongoose.Schema.Types.ObjectId],
It may be that the docs have changed since you posted this question though. Apologies if that's the case. Please see the Mongoose SchemaTypes docs for more info and examples.
I would try this.
user.friends.push(newFriend._id);
or
friends: [userSchema],
but i'm not sure if this is correct.

Categories