I am trying to do a simple search on a field that is a ref of another collection. Say I have the example collection of Invoices with a reference to a collection named client. So the example schema would look like so:
const invoiceSchema = new Schema({
name: {
type: String,
required: true
},
amount: {
type: Number,
required: true
},
client: {
type: Schema.Types.ObjectId,
ref: 'Client'
},
}
Then I have the client schema like so:
const clientSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
}
}
What I want to do is query the invoice schema and search for the name field in the client.
I have tried to use find and match with populate but that just returns the entire invoices collection and the client field is null on all of them:
const q = new RegExp(req.body.q, 'i');
invoices = await Invoice.find().populate({
path: 'client',
match: {
name: q
}
});
So how should I go about searching for a populated field with mongoose?
Related
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?
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);
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';
Is it possible to define fields at the schema level that are based off of another field using mongoose schemas?
For example, say I have this very simple schema:
const mongoose = require('mongoose')
const { Schema } = mongoose
const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
username_lower: {
type: String,
// calculated: this.username.toLowerCase()
},
email: {
type: String,
required: true,
unique: true
},
email_lower: { // for case-insensitive email indexing/lookup
type: String,
// calculated: this.email.toLowerCase()
},
password: {
type: String,
required: true
},
password_acceptable: {
type: Array,
// calculated: [
// this.password.toLowerCase(),
// this.password.toUpperCase()
// this.password.removeWhiteSpace(), // just an example
// ]
}
})
const User = mongoose.model('User', UserSchema)
module.exports = User
Is there something similar to the dummy "calculated" fields (that I've commented out) that would allow automatic field creation when the new document is saved? This would be very convenient and would reduce the clutter from having to manually define these fields on my back-end routes.
Thank you very much for your help!
you can do it by Pre middleware function, for more details
UserSchema.pre('save', function(){
this.username_lower = this.username.toLowerCase();
this.email_lower = this.email.toLowerCase();
// and so on ...
next();
});
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.