Mongoose find documents based on subdocument reference value - node.js

I am trying to grab documents based on subdocuments reference.
I have tried
Blog.find({"user.blocked" : false})
that query doesn't pull any documents results.
Here are my Schemas
const BlogSchema = new mongoose.Schema({
category: {type: String, trim: true},
user: {type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true},
title: {type: String},
description: {type: String},
}, {timestamps: true});
const UserSchema = new mongoose.Schema({
name: {type: String, required: true},
blocked: Boolean,
}, {timestamps: true});
mongoose.model('User', UserSchema);
mongoose.model('Blog', BlogSchema);

You are defining user as a reference, so you cannot query on fields of other collection. This is one of the differences with relational Databases, you cannot perform a JOIN.
Your alternative is to use an aggregation instead of a query, using the $lookup operator. You can check about it here

Related

Filter by id in on one to many field

Say I have this userSchema:
const userSchema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
email: {type: String, required: true, unique: true},
});
and this chatSchema:
const chatSchema = new Schema({
user_ids: {type: [String]},
});
I wonder if I could do a search to get all chats from a user that has their user_id inside chat's user_ids and how could I do that.
If you are referencing the user schema and you just need to query the user_id you can simply do it like this:
db.chat.aggregate([{$macth:{"user_ids" : user_id}}])

Mongoose find by ObjectID reference

I have two schemas:
let adSchema = mongoose.Schema (
{
author: {type: ObjectId, ref: 'User'},
title: {type: String, required: true },
town: {type: ObjectId, ref: 'Town', required: true},
}
);
And town schema:
let townSchema = mongoose.Schema (
{
name: {type: String, required:true, unique:true},
ads: [{type: ObjectId, ref: 'Ad'}]
}
);
I need to make query that finds all Ads by town.name
How can I do that?
You can request a town by name and use the mongoose populate method to fill the ads Array from town object.
You can find examples in the mongoose documentation:
http://mongoosejs.com/docs/populate.html

Search in a reference text field with Mongoose

I have this Schema
var users = new Schema({
name: {type: String, required: true},
email: {type: String, required: true},
password: {type: String, required: true},
following: [{type: Schema.ObjectId, ref: "users"}]
});
users.index({name: 'text'});
I want to use Mongoose to find users who they have "john" in their name and they are exists in following array of user of _id = x
in other way if it was SQL the query would be (it just example to illustrate the relations)
SELECT * FROM users where _id = x AND users.following.name LIKE '%john%'
I think that if following array was embedded in the user collections it would be easy to make.
How can i handle that in mongoose ?
I found the answer here http://mongoosejs.com/docs/populate.html
I used populate with match
.findById("x", {following: 1}).populate({ path: 'following',match: {$text: {$search: "john"}}})

Unique index on nested fields in Mongoose schema

Are these schemas valid?
var StudentSchema = new mongoose.Schema({
first_name: {type: String, required:true},
last_name: {type: String, required: true},
mother_name : {type: String, required: true},
siblings:[{
name:{type: String, required: true},
age:{type:Number, required: true},
school:{type:String, required:true}
}]
});
And this
var WinSchema = new mongoose.Schema({
event:{type: mongoose.Schema.Types.ObjectId, ref:'Event'},
winners : [{
student: {type: mongoose.Schema.Types.ObjectId, ref: 'Student'},
position: {type:String, enum:["First","Second","Third","Consolation"]}
}]
});
WinSchema.index({event:1,winners.student:1},{unique:true});
mongoose.model('Win',WinSchema);
Can we nest it as shown in StudentSchema?
Can we create a unique index on nested documents?
Yes you can nest it, see schema example here and of course you can create a index on nested documents here is the example.

Mongoose Model.find -> Edit -> Callback?

Sorry for the vague title, but what I'm trying to do is the following:
I've got 2 mongoose Models: posts and users (which can be the author of a post)
const Post = new Schema({
title: {type: String, required: true, unique: true},
content: {type: String, required: true},
date_created: {type: Date, required: true, default: Date.now},
authorId: {type: String, required: true}, // ObjectId
author: {type: Schema.Types.Mixed},
page: {type: Boolean, required: true, default: false}
});
post.find()
mongoose sends query to MongoDB
MongoDB returns documents
Middleware that retrieves the author based on the authorId property
Add found user to the posts author field
post.find callback
Is this possible?
yes, mongoose document references and population will do this for you.
const Post = new Schema({
// ...
author: {type: mongoose.Schema.Types.ObjectId, required: true, ref: "User"}
});
the ref: "User" tells Mongoose to use the "User" type as the object type. Be sure you have a "User" model defined with Mongoose or this will fail.
to load the full object graph, use the populate method of a query:
Post
.findOne(/* ... */)
.populate('author')
.exec(function (err, story) {
// ...
});
P.S. I cover this and more in my MongooseJS Fundamentals screencast package.

Resources