Mongoose only saves array of object _id value - node.js

I'm trying to post the messages array to mongoose database, but it only saves the _id property instead the content and sender property too. What am I doing wrong?
Group Schema:
var GroupSchema = new mongoose.Schema({
name: {
type: String,
required: true,
minlenght: 1,
trim: true
},
messages: {
type: [{type: Schema.ObjectId, ref: 'Message'}]
},
_creator: {
type: mongoose.Schema.Types.ObjectId,
required: true
}
});
Message Schema:
var MessageSchema = new mongoose.Schema({
content: {
type: String,
required: true,
minlenght: 1,
trim: true
},
sender: {
type: String,
required: true
}
});
POST /rooms route without saving
const messages = [];
for (const m of req.body.messages) {
messages.push(new Message(m));
}
var group = new Group({
name: req.body.name,
_creator: req.user._id,
messages: messages
});
JSON data in postman
When I run GET I only get back the messages objectID values

This is by design. You have a cross-reference between your GroupSchema and your MessageSchema via:
messages: {
type: [{type: Schema.ObjectId, ref: 'Message'}]
}
What this means is that GroupSchema/messages would only contain the ObjectIds of the messages cross referenced with your Messages collection.
You need to use populate to get the actual documents loaded.
The ref option is what tells Mongoose which model to use during
population.

Related

Mongoose - Reference a field from another table

I have two tables: Post and User and I want to reference the User name in the Post table.
I can reference the ID but I also need the name.
User model:
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
})
module.exports = mongoose.model("User", userSchema)
Post model:
const { ObjectId } = mongoose.Schema.Types
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
author: {
type: ObjectId,
ref: "User",
},
})
module.exports = mongoose.model("Post", postSchema)
In the doc they said:
Note: ObjectId, Number, String, and Buffer are valid for use as refs.
However, you should use ObjectId unless you are an advanced user and
have a good reason for doing so.
However I couldn't find an example on how I can do this.

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?

Right way to store Schemas on Mongoose?

I started learning some NodeJS, and how to make a REST API from Academind on YouTube, and learned what a relational and non-relational database is, etc.
With MongoDB, writes are rather cheap, so I want to minimize the number of reads that I do. At the moment I am trying to see how I could make an API, that will be for an app that's similar to discord's, although it'll be for fun.
Is this the right way to make a Schema?
const mongoose = require('mongoose')
const userSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true, unique: true},
email: { type: String, required: true },
password: { type: String, required: true }, // TODO: Hashing, etc
guilds: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
channels: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
// Only the X most recent messages
messages: [{
_id: mongoose.Schema.Types.ObjectId,
message: {type: String, required: true},
user: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}
}]
}],
// Only an X amount of users
users: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}]
}]
})
module.exports = mongoose.model('User', userSchema)
And then for the Guilds,
const mongoose = require('mongoose')
const guildSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
channels: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
// Only an X amount of messages
messages: [{
_id: mongoose.Schema.Types.ObjectId,
message: {type: String, required: true},
user: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}
}]
}],
// All the users
users: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}]
})
module.exports = mongoose.model('Guild', guildSchema)
Channel Schema
const mongoose = require('mongoose')
const channelSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
guild: {
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
channels: [{
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true }
}],
// The users of the guild, or just the channel?
// Could add a users object outisde of the guild object
users: [{
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true }
}]
}
})
module.exports = mongoose.model('Channel', channelSchema)
And finally for the messages
const mongoose = require('mongoose')
const messageSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
user: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
},
message: {type: String, required: true},
channel: {
guild: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
// Store more data for each message?
}
}
})
module.exports = mongoose.model('Message', messageSchema)
I am not sure if this is how a non-relational schema should look like. If it's not, how would I go about to store the data that I need?
Also, let's say that I POST a message on channel X on guild Y with the users A B and C, how would I go about to update all the entries, to add a message?
I've only used the User.find({_id: id}).exec().then().catch() so far, so I am not sure how to go about to update them.
Thanks in advance!
The messages collection should be on its own, do not embed it into any collection. This is not a good idea to embed data that will grow without limit.
The idea to store the last 5 messages into other collection looks painful to implement.
Embed denormalised data from all collections into the users collection seems like a problem when you will have to update guilds, channels, guilds users.
You may embed channels into guilds. Channels would not grow without a limit, should be a reasonable amount, less than 100 of channels per guild and probably it always used with a guild that they belong to. If not, consider not to embed channels into guilds.
The power of mongodb is to build the schema that reflects how your app is using data. I would recommend starting with normalized data. And when problems with creating, reading, updating, deleting data will occur then make appropriate changes in your mongoose schema to solve the problem. Premature optimization will only hurts in the long run.
As always an answer depends on details. Since I do not know all details I would recommend three part article by William Zola, Lead Technical Support Engineer at MongoDB. part 1 part 2 part 3

mongoose index creation issue after drop collection

I had created one index on the collection and it was created. But after the drop that collection and when I restarted node server then collection are created again but the index isn't can anybody suggest what is the cause?
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const validator = require('validator')
const FeatureSchema = new Schema({
name:{
type: String,
trim: true,
required: "Please enter a feature name!"
},
slug: String,
description: {
type: String,
trim: true
},
author: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: 'You must supply an author'
},
productID: {
type: mongoose.Schema.ObjectId,
ref: 'Product',
required: 'You must supply an product'
}
},{
timestamps: {
createdAt: 'createdDate',
updatedAt: 'updatedDate'
}
});
// Define our indexes
FeatureSchema.index({
name: 'text'
});
module.exports = mongoose.model('Feature', FeatureSchema);
try to stop mongodb service and restart it again.

Mongoose Populate - array

can someone please help me with population of this schema? I need to populate array of Staff by their userId.
var PlaceSchema = new Schema ({
name: { type: String, required: true, trim: true },
permalink: { type: String },
country: { type: String, required: true },
...long story :D...
staff: [staffSchema],
admins: [adminSchema],
masterPlace:{ type: Boolean },
images: []
});
var staffSchema = new Schema ({
userId: { type: Schema.Types.ObjectId, ref: 'Account' },
role: { type: Number }
});
var adminSchema = new Schema ({
userId: { type: Schema.Types.ObjectId, ref: 'Account'}
})
var Places = mongoose.model('Places', PlaceSchema);
I tried to use this query, but without success.
Places.findOne({'_id' : placeId}).populate('staff.userId').exec(function(err, doc){
console.log(doc);
});
Polpulation is intended as a method for "pulling in" information from the related models in the collection. So rather than specifying a related field "directly", instead reference the related fields so the document appears to have all of those sub-documents embedded in the response:
Places.findOne({'_id' : placeId}).populate('staff','_id')
.exec(function(err, doc){
console.log(doc);
});
The second argument just returns the field that you want. So it "filters" the response.
There is more information on populate in the documentation.

Resources