How to nest schemas in mongoose? - javascript

I'm trying to nest schemas using mongoose, but i got stuck and i don't really know why. Here is what i got.
My parent schema
const Comment = require("./Comment");
const BookSchema = new Schema({
_id: Number,
comments: [{ comment: Comment }],
ratings: [{ rate: Number }],
calculatedRating: Number
});
module.exports = Book = mongoose.model("book", BookSchema);
and child schema
const CommentSchema = new Schema(
{
userName: String,
rating: Number,
body: String,
submit_date: {
type: Date,
default: Date.now
}
},
{ _id: false }
);
module.exports = Comment = mongoose.model("comment", CommentSchema);
And with this setup im getting an error :
"TypeError: Invalid schema configuration: Model is not a valid type
at path comment."
I'm considering that i did something wrong with those exports but I'm not sure.

Your ./Comment should be:
const CommentSchema = new Schema(
{
userName: String,
rating: Number,
body: String,
submit_date: {
type: Date,
default: Date.now
}
},
{ _id: false }
);
module.exports = CommentSchema;
If you define as a new model as you did then it will create it's own collection and will be a new model instead of a sub document schema.

Related

How to export a subdocument without creating an empty collection

I am trying to create a document that has an array of another sub-document. I need to be able to export the sub-document for use elsewhere. I am using mongoose.model and this works, however, it creates an empty collection in my database that is just never used. How can I prevent this behavior?
Usage example:
const mongoose = require("mongoose");
const ChildSchema = new mongoose.Schema({
childName: String
});
const ParentSchema = new mongoose.Schema({
parentName: String,
children: [ChildSchema]
});
module.exports = {
Parent: mongoose.model("parent", ParentSchema),
Child: mongoose.model("child", ChildSchema)
}
You can do it with autoCreate and autoIndex options on your Schema:
const ChildSchema = new mongoose.Schema({
autoCreate: false,
autoIndex: false,
childName: String
});
const ParentSchema = new mongoose.Schema({
parentName: String,
children: [ChildSchema]
});

Mongoose Get only size of a array

I'm using Mongoose and a MongoDB.
I have three schemas user and genres and songs.
const userSchema = new Schema({
name: String,
age: String,
favorite_genres: {
type: Schema.Types.ObjectId,
ref: 'Genre'
}
});
const genreSchema = new Schema({
name: String,
songs: {
type: Schema.Types.ObjectId,
ref: 'Song'
}
});
const songSchema = new Schema({
title: String,
artist: String,
length: String,
year: String
});
those are simplifid schemas, but they will do for this puprose.
So when I query a user I want to populate the doc with the favorite genres. But there (due to the potential amount of data) not with the ids of all songs, but only the number of songs. How can I achieve that?
I tried virtuals but they don't work the way I wanted it.
What I'm looking for is sth like the following:
const user = await User.findById(userID).populate({path: 'favorite_genres', select: 'name', sizeof: 'songs'}).lean()
// or
const user = await User.findById(userID).populate({path: 'favorite_genres', select: ['name', 'songs.length']}).lean()
Does anyone have an idea?

How do I connect my mongoDB schema/models?

I'm new and trying to set up my noSQL DB model and am struggling. The intention is that "venues" can create events (tied to the venue), and "artists" can match-to and subsequently plan events. If you're an artist, you could also look at your dashboard and see the events you've played, so I need to connect Artists to Venues/events but don't know how.
Below is my Venue model. It works fine in my app, but where do I add Artists in?
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const VenueSchema = new Schema({
title: String,
image: String,
price: Number,
description: String,
location: String
});
module.exports = mongoose.model('Venue', VenueSchema);
Below is my Artist model. I haven't tested this one but I think it will work okay.
const mongoose = require('mongoose');
const { Schema } = mongoose;
const artistSchema = newSchema({
name: {
type: String,
required: [true, 'Artist must have a name']
},
genre: {
type: String
},
email: {
type: String,
required: [true, 'Contact email required']
},
})
Other than Artist and Venue, I'd like "events" to contain attributes "time" and "date". However, I have no idea where to fit events into the model.. How do I connect "events" between the two models?
I would design it like this
Venue schema (Same as yours): Where all the venues can be maintained independently of events and artists.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const VenueSchema = new Schema({
title: String,
image: String,
price: Number,
description: String,
location: String
});
module.exports = mongoose.model('Venue', VenueSchema);
Artist schema (same as yours): Where all the artists can be maintained independently of events and venues.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const artistSchema = newSchema({
name: {
type: String,
required: [true, 'Artist must have a name']
},
genre: {
type: String
},
email: {
type: String,
required: [true, 'Contact email required']
},
})
module.exports = mongoose.model('Artist', artistSchema);
Events schema: This is where artists and venue come together. Since there will be continuous operations on events (like updating progress) it can be done independently of artists and venues.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const eventSchema = new Schema({
venue_id: {
type: Schema.Types.ObjectId,
ref: 'Venue',
index: true
},
artist_id: {
type: Schema.Types.ObjectId,
ref: 'Artist',
index: true
},
created: {
type: Date, // Captures both date and time
default: Date.now
}
});
module.exports = mongoose.model('Event', eventSchema);

How to reach information already saved in other related models... MongoDB, NodeJS

I'm really new at this and I want to practice queries and tried to make a very different exercise but it didn't went as I expected.
I got three models:
const userSchema = new Schema({
info1: String,
info2: String,
},
const serviceSchema = new Schema(
{
name: String,
legalOwner: {
type: Schema.Types.ObjectId,
ref: 'User',
},
},
const orderSchema = new Schema(
{
client: { type: Schema.Types.ObjectId, ref: 'User' },
service: { type: Schema.Types.ObjectId, ref: 'Service' },
description: String
},
My users can behave like a legal owner or a client. I want to show the info that a user set as a LegalOwner, previously. And that is already saved in Mongo, How can I have access that data, is there a query for that? Do I need to set it in my model Order?
const orderSchema = new Schema(
{
client: { type: Schema.Types.ObjectId, ref: 'User' },
service: { type: Schema.Types.ObjectId, ref: 'Service' },
description: String,
legalOwner: { type: Schema.Types.ObjectId, ref: 'Service' },
},
I tried a lot of things on this query. But nothing works ...
await Order.findById(id).populate('service')
ObjectId are stored as _id within mongoDb as far as I am aware of.
Try this
const query = { _id: new ObjectID(id)};
await Order.findOne(query).populate('service')
Also import ObjectID from mongodb node_module as
import { ObjectID } from 'mongodb';

Typescript export default always executing

As a beginner in node js I cannot wrap my head around following problem.
import { createSchema, Type, typedModel } from "ts-mongoose";
const CompanySchema = createSchema(
{
companyName: Type.string({ required: true, unique: true })
},
{
timestamps: true
}
);
const Company = typedModel("Company", CompanySchema);
export { CompanySchema, Company };
This all works just fine until one point. When attempting to import this file.
import {CompanySchema, Company} from "./Company";
It executes typeModel method and stores the schema as expected. However, any other import of this file Company.ts reruns this method typeModel again. Which then fails because I can register schema with the name only once. How could I prevent of reruning this and still keep access to this object?
What would be general approach to this in order to keep access to both CompanySchema and Company object(as they will be later used in another schema as a reference)?
I don't know what the createSchema and typedModel are( if they are functions created by you or part of mongoose, the versions of mongoose ive worked with didnt have these functions )
...but I think you should not "createSchema" but define it instead.
e.g
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// define schema
const messageSchema = Schema({
sender: { type: Schema.Types.ObjectId, ref: 'User' },
recipient: { type: Schema.Types.ObjectId, ref: 'User' },
createdAt: { type: Date, default: Date.now },
deletedAt: { type: Date, default: undefined },
readAt: { type: Date, default: undefined},
message: { type: String, maxlength: 5000 }
});
// create a model based on that schema
const Message = mongoose.model('Message', messageSchema);
// Export the message model ... not the schema
module.exports.Message = Message;

Categories