Nestes Schema virtual - mongodb

I am trying to access the products collection in my find method. I added a .virtual method in order to access it but I currently get following error messsage:
MissingSchemaError: Schema hasn't been registered for model
"ProductDocument".
So far my implementation:
export type PriceDocument = Price & Document;
#Schema({ timestamps: true })
export class Price {
#Prop({
ref: 'ProductDocument',
required: true,
})
uid: string;
#Prop()
standardPrice: number;
#Prop({ required: true })
startDate: Date;
#Prop()
endDate: Date;
}
export const PriceSchema = SchemaFactory.createForClass<Price>(Price)
.index({
uid: 1, startDate: 1, endDate: 1,
}, { unique: true });
PriceSchema.virtual('products', {
ref: 'ProductDocument',
localField: 'uid',
foreignField: 'uid',
});
ProductPriceSchema.set('toObject', { virtuals: true });
ProductPriceSchema.set('toJSON', { virtuals: true });
This is how I try to access it in my find method
const productPriceDocument = await this.productPrice.find({
$and: queries, // dynamic queries
}).populate('products').exec();

Related

How to add timestamps fields and _id into nested schema by default

I have a correct schema User where fields _id, createdAt, updatedAt are written by default. But in schema Message it doesn't work.
export type UserDocument = HydratedDocument<User>;
#Schema({ timestamps: true, versionKey: false })
export class Message {
#Prop()
content: string;
}
#Schema({ timestamps: true, versionKey: false })
export class User implements UserInterface {
#Prop()
name: string;
#Prop()
email: string;
#Prop([{ type: mongoose.Schema.Types.ObjectId, ref: 'Message' }])
messages?: Message[];
}
export const UserSchema = SchemaFactory.createForClass(User);
Here is my function of message creating:
async createMessage() {
const user = await this.userModel.findById('63ee4fc044d93a4f6bebf934');
user.messages.push({ content: 'a' });
return await user.save();
}
And error is:
Cast to ObjectId failed for value "{ content: 'a' }" (type Object) at path "messages" because of "BSONTypeError"
But this snippet works fine:
async createUser(createUserDto: CreateUserDto): Promise<CreatedUserDto> {
return this.userModel.findOneAndUpdate(
{ name: createUserDto.name },
createUserDto,
{ upsert: true, new: true },
);
}
How to fix it?
Fixed id, correct implementation:
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
import { UserInterface } from '../interface/user.interface';
export type UserDocument = HydratedDocument<User>;
#Schema({ timestamps: true, versionKey: false })
export class Message {
#Prop()
content: string;
}
export const MessageSchema = SchemaFactory.createForClass(Message);
#Schema({ timestamps: true, versionKey: false })
export class User implements UserInterface {
#Prop()
name: string;
#Prop()
email: string;
#Prop({ type: [MessageSchema], default: [] })
messages?: Message[];
}
export const UserSchema = SchemaFactory.createForClass(User);

MissingSchemaError: Schema hasn't been registered for model "Product"

------------------------------
Here is Order Controller
-----------------------------
import nc from "next-connect";
import db from "../../../utils/db";
import Order from "../../../models/OrderModel";
import { isAuth } from "../../../utils/auth";
const handler = nc();
handler.use(isAuth);
handler.get(async (req, res) => {
try {
await db.connect();
const order = await Order.findById(req.body.order).populate({
path: "product",
model: "Product",
});
await db.disconnect();
res.send(order);
} catch (err) {
console.log(err);
}
});
export default handler;
--------------------------------------------------------------
Here is Order Schema
--------------------------------------------------------------
import mongoose from "mongoose";
const orderSchema = new mongoose.Schema(
{
product: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Product",
required: true,
},
],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
}
},
{ timestamps: true }
);
const Order = mongoose.models.Order || mongoose.model("Order", orderSchema);
export default Order;
----------------------------
Here is Product Schema
----------------------------
import mongoose from "mongoose";
const productSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
category: {
type: String,
required: true,
},
period: {
type: String,
required: true,
},
features: [{ type: String, required: true }],
},
{ timestamps: true }
);
const Product =
mongoose.models.Product || mongoose.model("Product", productSchema);
export default Product;
--------------------
I am getting this error: "MissingSchemaError: Schema hasn't been registered for model "Product".
Use mongoose.model(name, schema)"
There are also some orders including product ObjectId and I am trying to get the data using populate on the POSTMAN but getting this error.
I've really searched much before posting this but I've didn't solve the error

MongoDb aggregate query, how to select field from foreign table?

I am running a mongoDb query trying to get the data of my "User" which also include the "CounterParty.name" My aggregate query does get the user back, but does nothing with the fields from Counterparty. I went through the docs several times but cannot seem to figure it out.
My UserSchema
import { Schema, model } from "mongoose";
import mongoose from "mongoose";
export type UserDocument = mongoose.Document & {
email: string;
password: string;
status: string;
name: string;
counterParty: Schema.Types.ObjectId;
}
const userSchema = new Schema<UserDocument>(
{
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
name: {
type: String,
required: true
},
status: {
type: String,
default: "I am new"
},
counterParty: {
type: Schema.Types.ObjectId,
ref: "CounterParty",
}
},
{ timestamps: true }
)
export const User = model<UserDocument>('User', userSchema);
My CounterPartySchema
import { Schema, model } from "mongoose";
import mongoose from "mongoose";
export type CounterPartyDocument = mongoose.Document & {
name: string
}
const counterPartySchema = new Schema<CounterPartyDocument>(
{
name: {
type: String,
required: true,
unique: true,
trim: true
},
},
{ timestamps: true }
)
export const CounterParty = model<CounterPartyDocument>('CounterParty', counterPartySchema);
My query code
const user = await User.aggregate<any>([
{ '$match': { email: email } },
{
'$lookup': {
from: 'CounterParty',
localField: 'counterParty',
foreignField: '_id',
as: 'details'
}
}
])
console.log("user", user)
My console log statement now returns the user, but nothing to see of the counterParty.
Any help will be much appreciates! Cheers
Your aggregation query looks fine in the playground , maybe you dont have such _id: new ObjectId("...786") in the counterParty collection?

Is it possible to have in Mongodb (with mongoose and typegoose) an index on array of nested keys?

In mongodb (using mongoose and typegoose) is it possible to have an array index on a nested key?
export class Member extends Typegoose {
#prop({ required: true })
public email!: string;
#prop({ required: true })
private userId!: string
}
#index({ 'members.userId': 1 })
export class Group {
#arrayProp({ items: Member })
public members: Member[];
#prop()
name: string;
}
If so, how can I query this collection if I'd want to find a group by userId?
Like this?
Group.findOne({ usersIds: userId })
yes it is possible, here is how you can do it:
// NodeJS: 14.5.0
// MongoDB: 4.2-bionic (Docker)
import { getModelForClass, prop, index } from "#typegoose/typegoose"; // #typegoose/typegoose#7.3.0
import * as mongoose from "mongoose"; // mongoose#5.9.25 #types/mongoose#5.7.32
class Member {
#prop({ required: true })
public email!: string;
}
#index({ "members.email": 1 }, { unique: true }) // added unique to be easily testable
class Group {
#prop({ type: Member })
public members?: Member[];
#prop()
public name?: string;
}
const GroupModel = getModelForClass(Group);
(async () => {
await mongoose.connect(`mongodb://localhost:27017/`, { useNewUrlParser: true, dbName: "verifyMASTER", useCreateIndex: true, useUnifiedTopology: true });
await GroupModel.create({ name: "group1", members: [{ email: "h#h.h" }] });
try {
await GroupModel.create({ name: "group2", members: [{ email: "h#h.h" }] });
console.log("didnt fail");
} catch (err) {
// it should error
console.log("err", err);
}
console.log(await GroupModel.listIndexes());
await mongoose.disconnect();
})();
output of GroupModel.listIndexes:
[
{ v: 2, key: { _id: 1 }, name: '_id_', ns: 'verifyMASTER.groups' },
{
v: 2,
unique: true,
key: { 'members.email': 1 },
name: 'members.email_1',
ns: 'verifyMASTER.groups',
background: true
}
]

Schema hasn't been registered for model :mongoose

I have a model like this
const Schema = mongoose.Schema
const fileSchema = mongoose.Schema({
ownerId: { type: Schema.Types.ObjectId },
fileTypeId: { type: Schema.Types.ObjectId },
name: { type: String },
data: { type: Schema.Types.Mixed },
fileSize: { type: Number },
isHashInBlockchain: { type: Boolean },
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now }
})
fileSchema.virtual('file', {
ref: 'filetype',
localField: 'fileTypeId',
foreignField: '_id'
})
fileSchema.set('toObject', { virtuals: true })
fileSchema.set('toJSON', { virtuals: true })
module.exports = mongoose.model('useruploadedfiles', fileSchema)
I am referring filetype collection to this model
But when I run the following query
await File.find(query).populate({ path: 'file' }).select('_id name createdAt updatedAt').sort({ createdAt: -1 }).skip(limit * (pageNumber - 1)).limit(limit)
I am getting the following error
Schema hasn't been registered for model "filetype"
You have to import your model in your root app file.
model.js
const UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
trim: true,
},
name: {
type: String,
required: "Please supply a name",
trim: true
},
});
module.exports = mongoose.model("User", UserSchema);
app.js
mongoose.connect(process.env.DATABASE);
mongoose.Promise = global.Promise; // Tell Mongoose to use ES6 promises
mongoose.connection.on('error', (err) => {
console.error(`🙅 🚫 🙅 🚫 🙅 🚫 🙅 🚫 → ${err.message}`);
});
// READY?! Let's go!
require('./models/User')
router.js
const User = mongoose.model("User");
const getUsers = async (req, res) => res.json(await User.find({}));
app.get('/users', getUsers);