How to query and get documents from two collections on mongoose - node.js

I need to query documents from two collections together on mongoose.
I am familiar with SQL query and but not familiar with mongoDB.
I have two schema for Users, Messages like following.
Users
const UserSchema = new mongoose.Schema({
name: String,
email: {type: String, unique: true},
password: String,
avatar: {type: String, default: ""},
created_at: { type: Date, default: Date.now() }
});
module.exports = mongoose.model('User', UserSchema);
Messages
const MessageSchema = new mongoose.Schema({
message: { type: String, default: "" },
from: { type: String, default: "" },
to: { type: String: default: "" },
is_read: { type: Boolean, default: false },
channel: { type: String, default: ''},
created_at: { type: Date, required: true, default: Date.now }
});
module.exports = mongoose.model('Message', MessageSchema);
I need to get messages with "is_read" is "false".
I want to get "user name" and "avatar" together.
The "from" value of message should be matched with "_id" of User.

I think this post sums it up well: Mongoose - query to get data from multiple collections
Specifically the second upvoted answer mentions similarities between sql and mongodb, and goes on to explain how to link collections in mongoose queries.

Related

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});

Get info from 2 separate Mongo documents in one mongoose query

Im using MongoDb, and I have a workspace schema with mongoose (v4.0.1):
var Workspace = new mongoose.Schema({
name: {
type: String,
required: true
},
userId: {
type: String,
required: true
},
createdOn: {
type: Date,
"default": Date.now
}
});
And a user schema:
var User = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
organisation: {
type: String,
required: true
},
location: {
type: String,
required: true
},
verifyString: {
type: String
},
verified: {
type: Boolean,
default: false
},
password: {
type: String,
required: true
},
createdOn: {
type: Date,
"default": Date.now
},
isAdmin: {
type: Boolean,
default: false
}
});
So the Workspace userId is the ObjectID from the User document.
When Im logged in as an adminstrator, I want to get all workspaces, as well as the email of the user that owns the workspace.
What Im doing is getting very messy:
Workspace.find({}).exec.then(function(workspaceObects){
var userPromise = workspaceObects.map(function(workspaceObect){
// get the user model with workspaceObect.userId here
});
// somehow combine workspaceObjects and users
});
The above doesnt work and gets extremely messy. Basically I have to loop through the workspaceObjects and go retrieve the user object from the workspace userId. But because its all promises and it becomes very complex and easy to make a mistake.
Is there a much simpler way to do this? In SQL it would require one simple join. Is my schema wrong? Can I get all workspaces and their user owners email in one Mongoose query?
var Workspace = new mongoose.Schema({
userId: {
type: String,
required: true,
ref: 'User' //add this to your schema
}
});
Workspace.find().populate('userId').exec( (err, res) => {
//you will have res with all user fields
});
http://mongoosejs.com/docs/populate.html
Mongo don't have joins but mongoose provides a very powerfull tool to help you with you have to change the model a little bit and use populate:
Mongoose population
You have to make a few changes to your models and get the info of the user model inside your workspace model.
Hope it helps

Mongoose: find all referenced documents

I have 2 schemas:
var pollSchema = new mongoose.Schema({
title: String,
created: {
type: Date, default: Date.now
},
options: [{
label: String,
count: {
type: Number, default: 0
},
backgroundColor: {
type: String, default: '#fff'
}
}],
author:{
id:{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
var userSchema = new Schema({
username: {type: String, unique:true},
email: {type: String, unique:true, lowercase: true},
password: String
});
Now each poll will store data of it's author.
Questions:
How can I redesign my schemas - so I will be able to find all the polls belong to particular user?
Or should I leave the schemas the same and find another approach?
you can still find all the polls belonging to a particular user . You have the author.id for that.
Also you can keep an array as var userSchema = new Schema({
username: {type: String, unique:true},
email: {type: String, unique:true, lowercase: true},
password: String,
polls: []
});
And every time a user polls, push the userId inside the polls array, which you can later populate or get the count.

using a key value other than Schema.Types.ObjectId in mongoose

I am creating a collection w/n mongo using mongoose to populate related users. I have clinicians and patients. I want patients to have an array of clinicians as they are enrolledwith. Later I'll load a dashboard for clincian based on patient user "enrolledWith: "
Likely clincians will provide their email to patients to be marked in rolled. emails are username.
Can I use username for the Schema.Types.username?
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
name: String,
phoneNumber: String,
username: {
type: String,
required: true
},
password: {
type: String,
required: true
},
patient: {
// role: Boolean,
enrolledWith: [
{
type: mongoose.Schema.username,
ref: 'User'
}
],
gameTotalScore: Number,
},
// clinician: {
// role: Boolean
// },
role: {
type: String,
required: true
},
});

How to compare _id value of Models made using Mongoose?

I have the following two schemas of User and Critique and I've got the data persisted in MongoDB database:
var userSchema = mongoose.Schema({
critiques: [{ type: Schema.ObjectId, ref: 'Critique' }],
});
var User = mongoose.model("User", userSchema);
var critiqueSchema = mongoose.Schema({
author: {type: String, default: ''},
date: { type: Date, default: Date.now },
comment: { type: String, default: '' },
stars: { type: Number, default: 0 },
_user: { type: Schema.ObjectId, ref: 'User' }
});
var Critique = mongoose.model("Critique", critiqueSchema);
user.critiques[0]._id.equals(critique._id) is giving me undefined is not a function.
How to compare _id value of a User instance with the Critique instance?
The critiques field of your user object directly contains an array of ObjectIds, so it would just be:
user.critiques[0].equals(critique._id)
user.critiques would only contain full Critique objects if you chained a .populate('critiques') call in the find where you obtained user.

Resources