Creating a MongoDB schema with references to other schemas - javascript

I am having some difficulties understanding how construct my schemas and am hoping to get some help.
In short I have three schemas Company, User and Verification. I start by creating some companies and then create and add users to the companies.
I then log in to a webpage and use a form to add rows to a table (konto, beskrivning, projekt...). Then I save the verification to a MongoDB.
First question is: Would the current schemas work for my scenario? or do I need to change something. Have I entered redundant information?
Second question: In the VerificationSchema I would like to have an incrementing value (verificationNumber) for each company that starts by 1 then increases for every added verification. The counter should be separate for each company but shared with all users in the same company.
Verification.js
const VerificationSchema = mongoose.Schema({
verificationNumber: Number,
user :{type: mongoose.Schema.Types.ObjectId, ref: 'User'},
company: {type: mongoose.Schema.Types.ObjectId, ref: 'Company'},
rows: [{
konto: Number,
beskrivning: String,
projekt: String,
debet: Number,
kredit: Number
}]
});
Company.js
const CompanySchema = mongoose.Schema({
companyName: String,
users: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}],
verifications: [{type: mongoose.Schema.Types.ObjectId, ref: 'Verification'}]
});
User.js
const UserSchema = mongoose.Schema({
userName: String,
company: {type: mongoose.Schema.Types.ObjectId, ref: 'Company'],
verifications: [{type: mongoose.Schema.Types.ObjectId, ref: 'Verification'}]
});

Related

Many population layer mongose

I have a problem finding a solution to populate a filed populated(the number of populate unknowen)
export const FilesSchema = new mongoose.Schema(
{
name: {
type: String,
trim: true,
required: true,
unique: true,
},
children: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Files',
},
],
},
{ timestamps: true },
);
it represent a structure of file that can be a file or a folder.
a folder can contient another folder and another folder with files
the number of population are unknowen . any help with this ?
i found a solution
Say you have a user schema which keeps track of the user's friends.
const userSchema = new Schema({
name: String,
friends: [{ type: ObjectId, ref: 'User' }]
});
Populate lets you get a list of a user's friends, but what if you also wanted a user's friends of friends? Specify the populate option to tell mongoose to populate the friends array of all the user's friends:
User.
findOne({ name: 'Val' }).
populate({
path: 'friends',
// Get friends of friends - populate the 'friends' array for every friend
populate: { path: 'friends' }
});
https://mongoosejs.com/docs/populate.html#deep-populate

Mongoose populate subdocument in array

I have a Mongoose offer model explained below:
const OfferSchema = new Schema({
sections: [
{
title: String,
},
],
});
and order schema which has reference to to the first schema offer explained below:
const OrderSchema = new Schema({
offers: [
{
offer: { type: Schema.Types.ObjectId, ref: 'Offer' },
sections: [
{
section: { type: Schema.Types.ObjectId, ref: 'Offer.sections' }, // issue here
},
],
},
],
});
the problem that I can not populate sections here {section: { type: Schema.Types.ObjectId, ref: 'Offer.sections' }}
it gives me MissingSchemaError: Schema hasn't been registered for model "Offer.sections".
so is there any way to populate sections?
Unfortunately, Mongoose doesn't support this feature.
check the Github issue here
The alternative solution you can embed sections into the order schema

Converting to Mongo/mongoose from Mysql with relations

In a new project I started with MySQL but I want to convert it to mongodb / moongoose.
My pain here is the different relations I have in MySQL.
F.x. I have have users table
uid | firstname | lastname | email
and i housetable
hid | address | zipcode | city | ownerid
where ownerid is a user in the users table
I am a little unsure how I should design me schemas in mongoose to have an option a bit like the MySQL one.
My current user schema is like this
const userSchema = new mongoose.Schema({
firstname: String,
lastname: String,
email: String,
phone: Number,
password: String,
address: String,
zipcode: Number,
city: String,
bankname: String,
bankregno: Number,
bankaccno: Number,
userconfirmed: Boolean,
confirmtoken: String,
resettoken: String,
resettokenexpires: Date,
acceptmarketing: Boolean,
lastloggedin: Date,
disabled: Boolean
})
You can add a field for an array of houses in your userSchema to break it up and allow a one to many relation. You can do this by using subdocuments.
This could look something like this.
const houseSchema = new mongoose.Schema({
address: String,
zipcode: Number,
city: String,
})
const userSchema = new mongoose.Schema({
firstname: String,
lastname: String,
email: String,
phone: Number,
password: String,
bankname: String,
bankregno: Number,
bankaccno: Number,
userconfirmed: Boolean,
confirmtoken: String,
resettoken: String,
resettokenexpires: Date,
acceptmarketing: Boolean,
lastloggedin: Date,
disabled: Boolean,
houses: [houseSchema],
})
you can use mongoose populate, like this
const User = new mongoose.Schema({
House: { type: mongoose.Types.Schema.ObjectId, ref: "House" }
});
const House = new mongoose.Schema({
Number,
Road: String
});
(async () => {
const users = await User.find({}).populate("House");
// users = [
// {
// _id: 373890hfjklfhjkfh,
// House: {
// _id: dhkdhdlhjkld,
// Number: 378930,
// Road: fhjdlhdjkld
// }
// }
// ]
})();
If you are looking to relate both the schemas, this might help you. If you want more info, https://mongoosejs.com/docs/2.7.x/docs/populate.html
const User = mongoose.model('User', new mongoose.Schema({
firstname: {
type: String,
},
lastname: {
type: String,
},
email: {
type: String
}
}));
const Address = mongoose.model('Address', new mongoose.Schema({
owner: {
type: Schema.Types.ObjectId,
ref: 'User'
}
//rest of your address schema
}))

Mongoose model: calculate and automatically update average rating

I have a Movie model in Mongoose and this has a ratings key which is an array of numbers. I am looking for some sort of method I can add to this schema that automatically calculates the average rating when I add a new rating to the array. Does anyone know how this is done?
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var schema = new Schema({
title: String,
actors: String,
director: String,
length: Number,
description: String,
genre: String,
country: String,
year: Number,
ratings: [],
averageRating: Number,
reviews: [{type: Schema.Types.ObjectId, ref: 'Review'}],
pictureUrl: String
}, { usePushEach: true });
module.exports = mongoose.model('Movie', schema);
You can define a method on the schema to do two things: add a rating to the ratings property, and then update the averageRatings property. You would then call this method instead of directly updating the ratings property.

MongoDB - Mongoose: document structure/architecture

I have a relatively simple question, however, I keep getting stuck, over and over again. I think this is the fourth time I have tried to re-structure my documents to try and get the desired result.
I want to create a database in mongoose with the following structure:
A User has many groups, posts and comments. The groups, posts and comments all belong to a User. A post can belong to many groups, or none. And a comment belongs to a certain post.
Here is what I have so far:
UserSchema
var userSchema = mongoose.Schema({
local : {
email : String,
password : String,
username : String,
created: {type:Date, default: Date.now}
}
});
PostSchema
var PostSchema = new Schema({
url: String,
highlighted: String,
comment: String,
image: String,
timeStamp: String,
description: String,
title: String,
created: {type:Date, default: Date.now},
private: Boolean,
favorite: Boolean,
readlater: Boolean,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
comments: [{
text: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
}],
groups: [{
name: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
}]
});
groupSchema
var GroupSchema = Schema({
name : String,
created: {type:Date, default: Date.now},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
Although I may be wrong on this assumption, I think I have the post to user and comment to post relationship just the way it should be. Please correct me if I am wrong. The main problem I am having right now is with my group to post relationship. Currently, there is no relationship at all. As far as I can, it is almost as if the group belongs to the post, instead of the other way around. The only other way I can think to structure the group would be like so:
var GroupSchema = Schema({
name : String,
created: {type:Date, default: Date.now},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
posts: [{
title: String,
Url: String,
comments: [{
text: String
}]
etc....
}]
});
The only problem I can see in the structure above is that the post will be required to be part of a group, which I want to be optional. So as far as I can tell, this will not work either.
If there is any advice you can provide in regards to how this should be structured, it would help me greatly.
Thank you in advance.
Your best bet is to embed your groups and comment schemas inside of your post document. For example,
var GroupSchema = Schema({
name: String,
created: { type:Date, default: Date.now },
});
var CommentSchema = Schema({
text: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
var PostSchema = new Schema({
url: String,
...,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
comments: [CommentSchema]
groups: [GroupSchema]
});
Now, if you are looking for posts with a particular group, you can build a query as follows. You can build more complicated queries than this however.
Post.elemMatch("groups", {name: {$in: ["group1", "group2"]}}).then(...)

Categories