Mongoose find by ObjectID reference - node.js

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

Related

Mongoose find documents based on subdocument reference value

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

Translate mongo nested array query into mongoose

I have the following query working with mongo, it returns the expected result
db.getCollection('trainings').find({"sections.employees.employee":ObjectId("5d3afa1a58a7160ea451d1db")})
but when I try the following call with mongoose, it returns an empty array
Training.find({'section.employees.employee': "5d3afa1a58a7160ea451d1db"})
Need some helping to translate the mongo query to mongoose.
If you need anything else just add a comment and I will post here.
It's worth mentioning that I have already tried passing a new ObjectId with the String value, but it also returns an empty array.
Edit: Query usage
return await Training.find({'section.employees.employee': "5d3afa1a58a7160ea451d1db"})
Edit: Model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const EmployeeSection = new Schema({
employee: {type: Schema.Types.ObjectId, ref: 'Employee', required: true},
fulfilled: {type: Boolean, default: null},
});
const Section = new Schema({
order: {type: Number, required: true},
date: {type: Date},
employees: {type: [EmployeeSection]},
answers: {type: Number},
hits: {type: Number}
});
const GoalSchema = new Schema({
understanding: {type: Number, required: true},
fixation: {type: Number, required: true}
});
const Evidence = new Schema({
description: {type: String, required: true},
file: {type: String}
});
const Question = new Schema({
participants: {type: Number},
answers: {type: Number},
hits: {type: Number}
});
const TrainingSchema = new Schema({
company: {type: Schema.Types.ObjectId, ref: 'Company', required: true, index: true},
creationDate: { type: Date, default: Date.now },
title: {type: String},
obs: {type: String},
questionNumber: {type: Number},
reference: {type: String},
sections: {type: [Section]},
goals: {
answers: {type: GoalSchema, required: true},
hits: {type: GoalSchema, required: true}
},
evidences: {type: [Evidence]},
questions: {type: [Question]},
area: {type: Schema.Types.ObjectId, ref: 'TrainingArea', required: true},
});
const Training = mongoose.model('Training', TrainingSchema);
module.exports = Training;
I am willing to change the Model schema, if the problem really lays there, but didn't really want to do it.
Why its always a typo?
db.getCollection('trainings').find({"sections.employees.employee":ObjectId("5d3afa1a58a7160ea451d1db")})
Training.find({'section.employees.employee': "5d3afa1a58a7160ea451d1db"})
Forgot s on sections
Made the problem a bit easier for me.
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/training", { useNewUrlParser: true })
const util = require("util")
const Schema = mongoose.Schema;
const EmployeeSection = new Schema({
employee: {type: Schema.Types.ObjectId, ref: 'Employee', required: true}
});
const Section = new Schema({
employees: {type: [EmployeeSection]}
});
const TrainingSchema = new Schema({
sections: {type: [Section]}
});
const Training = mongoose.model('Training', TrainingSchema);
Training.find(
{
"sections.employees.employee": mongoose.Types.ObjectId("5d3afa1a58a7160ea451d1db")
})
.exec()
.then(result => {
console.log(util.inspect(result, false, null, true /* enable colors */))
}).catch(err =>{
console.log(err)
})

Mongoose populate followers same document

I need to populate ObjectId parameters from the same Schema of users What am trying to do is I have 'Users' document and each record has followers and the ref is the same schema of users.
var userSchema = new Schema({
username: {type: String, unique: true, trim: true},
password: {type: String},
email: {type: String, trim: true},
avatar: {type: String},
fullname: {type: String},
bio: {type: String},
phone: {type: Number},
country: {type: String},
postal: {type: Number},
followers: [{ type: Schema.ObjectId, ref: 'User' }],
followed: [{ type: Schema.ObjectId, ref: 'User' }],
registered: {type: Date, default: Date.now}
});
var User = mongoose.model('users',userSchema);
Now when I tried to print the user information followers array return with ObjectId not the whole information
I try to print with this snippet
User.find().exec(function(error, groups) {
return res.status(200).send(groups);
});
What you want to achieve here is
User.find({})
.populate('followers')
.populate('followed')
.then(users => {
})
This will populate with both the followers and followed with their respective user objects

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 many to many relationship with additional data

Product Schema:
var ProductSchema = new Schema({
productName: {type: String, required: true},
});
Client schema:
var ClientSchema = new Schema({
clientName: {type: String, required: true},
products: [{ type : mongoose.Schema.ObjectId, ref : 'Product'}],
});
How can I add additional fields to the relationship? For example add field quantity:
var ClientSchema = new Schema({
clientName: {type: String, required: true},
products: [{ type : mongoose.Schema.ObjectId, ref : 'Product', quantity: Number}],
});

Resources