Mongoose/MongoDB Empty SubSchema Array - node.js

I have a model in Mongoose that looks like this:
const orderLogSchema = mongoose.Schema(
{
removed: { type: String, required: true },
},
{
timestamps: true,
}
)
const orderSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
orderItems: [
{
name: { type: String, required: true},
qty: { type: Number, required: true},
image: { type: String, required: true},
price: { type: Number, required: true},
product: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'Product'},
}
],
shippingAddress: {
address: { type: String, required: true },
city: { type: String, required: true },
postalCode: { type: String, required: true },
country: { type: String, required: true },
},
paymentMethod: {
type: String,
required: true,
},
paymentResult: {
id: { type: String },
status: { type: String },
update_time: { type: String },
email_address: { type: String },
},
taxPrice: {
type: Number,
required: true,
default: 0.0
},
shippingPrice: {
type: Number,
required: true,
default: 0.0
},
totalPrice: {
type: Number,
required: true,
default: 0.0
},
isPaid: {
type: Boolean,
required: true,
default: false
},
paidAt: {
type: Date,
},
isDelivered: {
type: Boolean,
required: true,
default: false
},
deliveredAt: {
type: Date,
},
couponCode: {
type: Object,
required: false
},
orderVerifyLog: [orderLogSchema],
}, {
timestamps: true
})
I need to be able to empty out the orderVerifyLog which is populated with the orderLogSchema. I have tried a bunch of things most recently I pulled the order into a variable, and I am able to access orderVerifyLog by using order.orderVerifyLog but I cant figure out how to empty out that orderLogSchema. I tried:
order.orderVerifyLog = []
order.save()
Is there an easy way to work with that "sub" schema and zero it out?
Basically I am pulling the log items from that schema for an order and displaying them on my front-end. Then I was to fire off an action to clears it out so they don't display every time the order is loaded (Only want them to show once). I also tired to loop over each item in the orderVerifyLog and use pull to remove them, but for some reason it always leaves one in there.

Related

React mongoose validation failed

I am trying to store order data but getting following error when adding it to mongoose:
Request:
Response:
Here is my source Code:
placeOrder Handler:
const placeOrderHandler = () => {
dispatch(
createOrder({
orderItems: cartItems,
shippingAddress: {
address: shippingAddress.address,
city: shippingAddress.city,
postalCode: shippingAddress.postalCode,
country: shippingAddress.country,
},
paymentMethod: paymentMethod,
itemPrice: cart.itemPrice,
shippingPrice: cart.shippingPrice,
taxPrice: cart.taxPrice,
totalPrice: cart.totalPrice,
})
);
};
orderModel.js
const mongoose = require("mongoose");
const orderSchema = mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
orderItems: [
{
name: { type: String, required: true },
qty: { type: Number, required: true },
image: { type: String, required: true },
price: { type: Number, required: true },
product: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Product',
},
},
],
shippingAddress: {
address: { type: String, required: true },
city: { type: String, required: true },
postalCode: { type: String, required: true },
country: { type: String, required: true },
},
paymentMethod: {
type: String,
required: true,
},
paymentResult: {
id: { type: String },
status: { type: String },
update_time: { type: String },
email_address: { type: String },
},
taxPrice: {
type: Number,
required: true,
default: 0.0,
},
shippingPrice: {
type: Number,
required: true,
default: 0.0,
},
totalPrice: {
type: Number,
required: true,
default: 0.0,
},
isPaid: {
type: Boolean,
required: true,
default: false,
},
paidAt: {
type: Date,
},
isDelivered: {
type: Boolean,
required: true,
default: false,
},
deliveredAt: {
type: Date,
},
},
{
timestamps: true,
}
);
const Order = mongoose.model("Order", orderSchema);
module.exports = Order;
If I am not wrong it is throwing error on orderItems:, but I am sending array of objects data which I have already defined in my orderModel.js.
As #Ernesto mentioned I was writing product in my schema instead of productID. Here is the correct way:
orderItems: [
{
name: { type: String, required: true },
qty: { type: Number, required: true },
image: { type: String, required: true },
price: { type: Number, required: true },
productID: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Product',
},
},
],

How can i calculate daily, weekly or monthly sales from my MongoDB data?

Here is my orders schema with Javascript mongoose;
import mongoose from 'mongoose';
const orderSchema = new mongoose.Schema(
{
orderItems: [
{
name: { type: String, required: true },
qty: { type: Number, required: true },
image: { type: String, required: true },
price: { type: Number, required: true },
product: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product',
required: true,
},
},
],
shippingAddress: {
fullName: { type: String, required: true },
address: { type: String, required: true },
city: { type: String, required: true },
postalCode: { type: String, required: true },
country: { type: String, required: true },
lat: Number,
lng: Number,
},
paymentMethod: { type: String, required: true },
paymentResult: {
id: String,
status: String,
update_time: String,
email_address: String,
},
itemsPrice: { type: Number, required: true },
shippingPrice: { type: Number, required: true },
taxPrice: { type: Number, required: true },
totalPrice: { type: Number, required: true },
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
seller: { type: mongoose.Schema.Types.ObjectID, ref: 'User' },
isPaid: { type: Boolean, default: false },
paidAt: { type: Date },
isDelivered: { type: Boolean, default: false },
deliveredAt: { type: Date },
},
{
timestamps: true,
}
);
const Order = mongoose.model('Order', orderSchema);
export default Order;
And for the case of sellers how could I do the same for specific sellers.
I would like to create charts and graphs with that data so any help counts. Thank You!

Model.find is not a function mongoose

I have a mini casino game and have a mongoose model defined as following:
const jackpotSchema = mongoose.Schema({
round_id: {
type: String,
default: uniqid(),
required: true,
},
createdAt: {
type: Date,
required: true,
default: Date.now
},
closedAt: {
type: Date,
},
startedAt: {
type: Number,
},
roundSecret: {
type: String,
required: true,
},
random_org_hash: {
type: String,
},
random_org_obj: {
type: String
},
roundSecretHash: {
type: String,
},
winningPercentage: {
type: Number,
// required: true,
// first 5 characters of the secret hash, converted into decimal then divided by 10K
},
publicHash: {
type: String,
required: true,
// SHA-256 roundSecret + winningPercentage
},
finalHash: {
type: String,
},
winningTicket: {
type: Number,
},
winningDepositIndex: {
type: Number,
},
deposits: [{
uid: {
type: String,
required: true,
},
user: {
type: String,
required: true,
},
nonce: {
type: Number,
},
amount: {
type: Number,
required: true,
},
user_avatar: {
type: String,
},
ticketRangeMin: {
type: Number,
required: true,
},
ticketRangeMax: {
type: Number,
required: true,
},
referral: {type: String},
timestamp: {type: Date},
timestamp_readable: {type: String}
}],
total: {
type: Number,
required: true,
default: 0,
},
totalTickets: {
type: Number,
default: 0,
},
winner: {
type: String,
default: "",
},
winner_avatar: {
type: String,
},
active: {
type: Boolean,
default: true,
required: true,
},
open: {
type: Boolean,
required: true,
default: true,
},
roundTime: {
type: Number,
// default: potConfig.potLength,
default: 20000,
},
success: {
type: Boolean,
},
fee: {
type: Number,
default: potConfig.potFee,
}
})
module.exports = mongoose.model("Jackpot", jackpotSchema)
When running my app locally, I experience no errors.
However when running on a ubuntu production environment, I get the following error:
Jackpot.find is not a function
The stack trace says that the error is coming from db_utils.js
which looks like the following:
const Jackpot = require("./models/Jackpot");
...
async retrieveStats () {
var jackpots = await Jackpot.find().lean();
}
I have checked to see whether my module.exports was defined correctly, and it is. Not sure why this error is happening.
My local and production node versions match.
12.18.4
Don't you need to do
const jackpotSchema = new mongoose.Schema({...})
instead of
const jackpotSchema = mongoose.Schema({...})

Mongoose Subdocument for Geojson

I am not able to define a correct reusable Point Schema. I just copied the example schema in https://mongoosejs.com/docs/geojson.html
This is the error I'm encountering when starting the node.js app
/home/******/projects/realista-api/node_modules/mongoose/lib/schema.js:418
throw new TypeError('Invalid value for schema path ' + prefix + key + '');
^
TypeError: Invalid value for schema path coordinates
I already tried using a non-reusable schema. By directly defining it at the parent schema and it works
coordinates: {
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
},
Here is the code
import { Schema, Document } from 'mongoose';
interface Point extends Document {
type: string,
coordinates: Array<number>,
}
const PointSchema: Schema = new Schema({
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
}, {
id: false
});
export {
Point,
PointSchema,
}
I'm using that as subdocument in another schema
const ProjectSchema: Schema = new Schema({
owner: {
type: Schema.Types.ObjectId,
ref: 'User',
required: false,
},
logo: {
type: String,
required: false,
},
name: {
type: String,
required: true,
},
location: {
type: String,
required: false,
},
suburb: {
type: String,
required: false,
},
stateCode: {
type: String,
required: false,
},
country: {
type: String,
required: false,
},
countryName: {
type: String,
required: false,
unique: true,
sparse: true,
},
coordinates: PointSchema,// this is the field in question
commission: {
type: Schema.Types.Decimal128,
required: false,
},
tax: {
type: Schema.Types.Decimal128,
required: false,
},
propertyType: {
type: Schema.Types.ObjectId,
ref: 'PropertyType',
required: true,
},
address: {
type: String,
required: false,
},
title: {
type: String,
required: false,
},
description: {
type: String,
required: false,
},
videoTour: {
type: String,
required: false,
},
matterPortUrl: {
type: String,
required: false,
},
currency: {
type: String,
required: false,
},
minPrice: {
type: Schema.Types.Decimal128,
required: false,
},
maxPrice: {
type: Schema.Types.Decimal128,
required: false,
},
otherPrice: {
type: String,
required: false,
},
featureLandSizeMin: {
type: String,
required: false,
},
featureLandSizeMax: {
type: String,
required: false,
},
featureLandSizeUnit: {
type: String,
required: false,
},
featureBuiltStart: {
type: Date,
required: false,
},
featureBuiltEnd: {
type: Date,
required: false,
},
featureNumOfLevel: {
type: Number,
required: false,
},
featureNumOfUnit: {
type: Number,
required: false,
},
featureFlooring: {
type: String,
required: false,
},
featureExterior: {
type: String,
required: false,
},
featureConcierge: {
type: String,
required: false,
},
indoorFeatures: {
type: String,
required: false,
},
outdoorFeatures: {
type: String,
required: false,
},
minBedrooms: {
type: Number,
required: false,
},
maxBedrooms: {
type: Number,
required: false,
},
minBathrooms: {
type: Schema.Types.Decimal128,
required: false,
},
maxBathrooms: {
type: Schema.Types.Decimal128,
required: false,
},
minParking: {
type: Number,
required: false,
},
maxParking: {
type: Number,
required: false,
},
csvVariationPending: {
type: Boolean,
required: false,
default: false,
},
isPrivate: {
type: Boolean,
required: false,
default: false,
},
status: {
type: Boolean,
required: false,
default: false,
},
variations: [{
type: Schema.Types.ObjectId,
ref: 'ProjectVariation',
}],
deletedAt: {
type: Date,
required: false,
}
}, {
collection: 'projects',
timestamps: true,
strict: false,
});
What am I doing wrong? Thanks in advance.
Was able to make it work. Hope this helps others who are developing using node.js
The issue was caused by 2 things:
Mongoose, when declaring subdocuments (nested objects or array of objects), gets confused when there is a type field in the document since in Mongoose concept, it is a reserved word for declaring the type of field. In my case, the type key comes from GeoJSON since it is required by MongoDB to be in that format. Here is a link from mongoose docs for better understanding.
What I just did is change PointSchema to this
import { Schema, Document } from 'mongoose';
interface Point extends Document {
type: string,
coordinates: Array<number>,
}
const PointSchema: Schema = new Schema({
type: {
$type: String,
enum: ['Point'],
required: true
},
coordinates: {
$type: [Number],
required: true
}
}, {
_id: false,
typeKey: '$type',
});
export {
Point,
PointSchema,
}
I'm also having a problem w/ circular dependency in node.js when importing/requiring the PointSchema. This error
/home/******/projects/realista-api/node_modules/mongoose/lib/schema.js:418 throw new TypeError('Invalid value for schema path ' + prefix + key + ''); ^ TypeError: Invalid value for schema path coordinates
occurred because PointSchema is undefined when I'm using it in ProjectSchema.
W/c justifies why issues in Mongoose Github suggest that mostly when they encounter that error, it is because of misspelled types (ObjectID instead of ObjectId), or in my case undefined w/c is invalid type.

How should I store page and subpage in collection with mongoose

I'm trying to create simple CMS with the ability to add new pages to the site. I have currently created a Collection called Pages:
var PageSchema = new Schema({
name_en: {
type: String,
required: true
},
name_nl: {
type: String,
required: true
},
slug_en:{
type: String,
required: true
},
slug_nl:{
type: String,
required: true
},
content_en: {
type: String,
required: true
},
content_nl: {
type: String,
required: true
},
visible: {
type: Number,
required: true,
default: 1
},
is_headMenu: {
type: Number,
require: true,
default: 0
},
is_footerMenu: {
type: Number,
require: true,
default: 0
},
date: {
type: Date,
default: Date.now
}
});
This collection store all pages, but after a few days I needed to add an option to also store sub-pages to existing pages.
I was thinking of creating an object inside of the Page Schema to hold all the sub-pages.
Like this:
var subPage = new Schema({
name_nl: {
type: String,
required: true
},
name_en: {
type: String,
required: true
},
slug_en:{
type: String,
required: true
},
slug_nl:{
type: String,
required: true
},
content_en: {
type: String,
required: true
},
content_nl: {
type: String,
required: true
},
visible: {
type: Number,
required: true,
default: 1
}
});
var PageSchema = new Schema({
name_en: {
type: String,
required: true
},
name_nl: {
type: String,
required: true
},
slug_en:{
type: String,
required: true
},
slug_nl:{
type: String,
required: true
},
content_en: {
type: String,
required: true
},
content_nl: {
type: String,
required: true
},
visible: {
type: Number,
required: true,
default: 1
},
is_headMenu: {
type: Number,
require: true,
default: 0
},
is_footerMenu: {
type: Number,
require: true,
default: 0
},
subPages: [
subPage
],
date: {
type: Date,
default: Date.now
}
});
But I cant use it because after creating a Page I'm required to fill the object 'subPage' because it's required. I don't want that. I want to add them whenever I want, and this way its not possible. How should I do it properly?

Resources