I am using molecularjs actions to enter data into my database. Primarily I am using NodeJS with mongoose to define models. So far I am able to create a model but when I try to create an one-to-many relation it gives me this error
errors: { 'deliveryParcels.0': CastError: Cast to [ObjectId] failed
for value "[{"parcelId":"LHE660851871415","address":"24 E muhafiz town
lahore","type":"COD","addressLocation":{"lat":31.4532941,"lng":74.2166403},"customerName":"ALI
MALHI","customerPhone":"3314488396","processingStatus":"pending","amount":2500,"vendorOrderId":"other"}]"
at path "deliveryParcels.0"
I want both collections rider-tasks and delivery-parcels to be created simultaneously but only the rider-tasks collection gets created but not the delivery-parcels. What am I doing wrong in my schema?
Here are my models
rider-tasks model
import mongoose, { Schema } from "mongoose";
import { getDbConnection } from "../../../utils/db/db-connect";
/* eslint-disable id-blacklist */
import { IRiderTaskModel } from "../interfaces/rider-task.interface";
const RiderTaskSchema: Schema<IRiderTaskModel> = new Schema<IRiderTaskModel>(
{
_id: { type: String, required: true, unique: true },
riderId: { type: String, required: true },
totalAmount: { type: Number, required: true },
riderName: { type: String, required: true },
cityId: { type: String, required: true },
cityName: { type: String, required: true },
status: { type: String, required: true },
adminName: { type: String, required: true },
adminId: { type: String, required: true },
createdAt: { type: Date, required: true },
deliveryParcels: [
{
type: Schema.Types.ObjectId,
ref: "delivery-parcels",
},
],
},
{ _id: true }
);
const RiderTask = getDbConnection("deliveryManagement").model<IRiderTaskModel>(
"rider-tasks",
RiderTaskSchema
);
export { RiderTask };
delivery-parcels
import mongoose, { Schema } from "mongoose";
import { getDbConnection } from "../../../utils/db/db-connect";
import { IDeliveryParcelModel } from "../interfaces/delivery-parcels.interface";
const DeliveryParcelsSchema: Schema<IDeliveryParcelModel> = new Schema<IDeliveryParcelModel>(
{
parcelId: { type: String, required: true },
address: { type: String, required: true },
addressLocation: {
lat: { type: Number, required: true },
lng: { type: Number, required: true },
},
customerName: { type: String, required: true },
customerPhone: { type: String, required: true },
processingStatus: { type: String, required: true },
amount: { type: Number, required: true },
riderTaskId: { type: Schema.Types.String, ref: "rider-tasks" },
type: { type: String, required: true, enum: ["COD", "NONCOD"] },
postedStatus: {
status: { type: String },
statusKey: { type: String },
signature: { type: String },
reason: { type: String },
checkBoxData: [{ type: String }],
adminId: { type: String },
adminName: { type: String },
},
}
);
const DeliveryParcels = getDbConnection(
"deliveryManagement"
).model<IDeliveryParcelModel>("delivery-parcels", DeliveryParcelsSchema);
export { DeliveryParcels };
My service
private async createdRiderTaskHandler(ctx: Context<IRiderTaskModel>) {
const { params } = ctx;
const finalData: IParcelData[][] = await Promise.all(
params.deliveryParcels.map((parcel) =>
this.broker.call("parcel-data.getParcels", {
id: parcel.parcelId,
})
)
);
const wrongParcels: string | any[] = [];
const check = finalData[0].filter(
(data) => data.currentStatus.status === "Dispatched"
)[0];
if (check) {
wrongParcels.push(check.parcelId);
const parcel = wrongParcels.join("\r\n");
throw new Error(
'These parcels "' + parcel + '" have already been dispatched'
);
}
const codAmount = params.deliveryParcels
.filter((data, i) => data.type === "COD")
.reduce((total, b) => total + b.amount, 0);
const customId = "RTD-" + Math.floor(100000 + Math.random() * 900000);
try {
const taskData = omit({
...params,
_id: customId,
totalAmount: codAmount,
forceAssignment: false,
createdAt: new Date(),
});
const data = await RiderTask.create(taskData);
return { message: data };
} catch (error) {
this.logger.error(error);
return error;
}
}
Related
Below code snippets contain 2 schemas. I am trying to fetch all club items that does NOT have a booking with a given date and time in the booking schema. As you can see the booking schema has a clubItem property where it takes an object. I want to get the club items that is not booked in the given date and time.
For example if there is a booked room from 21-11-2022, 9-10, I want all available club items to be fetched except that booked club item. The last code snippet represents my approach for tackling this issues but I can't quite get what I want. I tried to aggregation and tried to understand its concept but I am having issues implementing my condition.
const { default: mongoose } = require("mongoose");
const { PaymentStatusStrings, BookingStatusStrings, PaymentMethodStrings } = require("../utils/enums");
const { ClubItem } = require("./club_item");
const bookingSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
club: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Club',
required: true
},
clubItems: {
type: ClubItem.schema,
required: true
},
date: {
type: String,
required: true
},
startingTime: {
type: String,
required: true
},
endingTime: {
type: String,
required: true
},
totalHours: {
type: Number,
required: true
},
extraTime: {
type: Number,
required: true,
default: 0
},
subtotal: {
type: Number,
required: true
},
tax: {
type: Number,
required: true
},
totalPrice: {
type: Number,
required: true
},
paymentStatus: {
type: String,
enum: Object.values(PaymentStatusStrings),
required: true
},
status: {
type: String,
enum: Object.values(BookingStatusStrings),
required: true
},
paymentMethod: {
type: String,
enum: Object.values(PaymentMethodStrings),
required: true
},
DateTimeStamp:
{
type: Date,
default: Date.now
}
})
bookingSchema.virtual('id').get(function () {
return this._id.toHexString();
});
bookingSchema.set('toJSON', {
virtual: true,
});
exports.Booking = mongoose.model('Booking', bookingSchema);
const { default: mongoose } = require("mongoose");
const { CategoryStrings, ClubItemStatusStrings } = require("../utils/enums");
const clubItemSchema = mongoose.Schema({
name: {
type: String,
required: true
},
pricePerHour: {
type: Number,
required: true
},
minCapacity: {
type: Number,
required: true
},
maxCapacity: {
type: Number,
required: true
},
multiplayer: Boolean,
description: String,
image1: {
type: String,
required: true
},
image2: String,
image3: String,
category: {
type: String,
enum: Object.values(CategoryStrings),
required: true
},
club: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Club',
required: true
},
status: {
type: String,
enum: Object.values(ClubItemStatusStrings),
required: true
}
})
clubItemSchema.virtual('id').get(function () {
return this._id.toHexString();
});
clubItemSchema.set('toJSON', {
virtual: true,
});
exports.ClubItem = mongoose.model('ClubItem', clubItemSchema);
const { default: mongoose } = require("mongoose");
const { CategoryStrings, ClubItemStatusStrings } = require("../utils/enums");
const clubItemSchema = mongoose.Schema({
name: {
type: String,
required: true
},
pricePerHour: {
type: Number,
required: true
},
minCapacity: {
type: Number,
required: true
},
maxCapacity: {
type: Number,
required: true
},
multiplayer: Boolean,
description: String,
image1: {
type: String,
required: true
},
image2: String,
image3: String,
category: {
type: String,
enum: Object.values(CategoryStrings),
required: true
},
club: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Club',
required: true
},
status: {
type: String,
enum: Object.values(ClubItemStatusStrings),
required: true
}
})
clubItemSchema.virtual('id').get(function () {
return this._id.toHexString();
});
clubItemSchema.set('toJSON', {
virtual: true,
});
exports.ClubItem = mongoose.model('ClubItem', clubItemSchema);
const express = require('express');
const { Booking } = require('../../models/booking');
const { ClubItem } = require('../../models/club_item');
const { Club } = require('../../models/club');
const { User } = require('../../models/user');
const router = express.Router();
router.get('/getPlaystationRooms/:datetime', async (req, res) => {
const bookingDateTime = req.params.datetime
const clubItems = await ClubItem.aggregate([
{
$lookup: {
from: "booking",
localField: "_id",
foreignField: "clubItems._id",
as: "freeClubItems"
}
}
])
// const availableClubItems = [];
// clubItems.forEach(async clubItem => {
// const booking = Booking.findOne({ 'clubItems._id': clubItem._id}).where({date: bookingDateTime})
// if(!booking)
// {
// availableClubItems.push(clubItem);
// }
// })
console.log(clubItems);
res.status(200).send(clubItems);
})
module.exports = router;
my commented approach is implementing the logic with foreach loop and pushing a club item into an empty array if the booking with the given date, time and clubItemID is not found.
my 2nd approach is using aggregation using $lookup and $match but i reached no where.
router.get('/getPlaystationRooms/:datetime', async (req, res) => {
const bookingDateTime = req.params.datetime
const clubItems = await ClubItem.aggregate([
{
$lookup: {
from: "booking",
localField: "_id",
foreignField: "clubItems._id",
as: "freeClubItems"
}
}
])
// const availableClubItems = [];
// clubItems.forEach(async clubItem => {
// const booking = Booking.findOne({ 'clubItems._id': clubItem._id}).where({date: bookingDateTime})
// if(!booking)
// {
// availableClubItems.push(clubItem);
// }
// })
console.log(clubItems);
res.status(200).send(clubItems);
})
Here i have two mongoose models orders and users which have one to many relationship.
user.model.js
import mongoose from "mongoose";
const userSchema = mongoose.Schema(
{
firstname: {
type: String,
required: [true, "Name is required"],
},
lastname: {
type: String,
required: [true, "LastName is required"],
},
email: {
type: String,
required: [true, "Email is required"],
unique: true,
},
password: {
type: String,
required: [true, "Password is required"],
},
isAdmin: { type: Boolean, default: false },
},
{
timestamps: true,
}
);
const User = mongoose.model("User", userSchema);
export default User;
order.model.js
import mongoose from "mongoose";
const orderSchema = mongoose.Schema(
{
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
customerId: { type: String },
paymentIntentId: { type: String },
products: [
{
id: { type: String },
name: { type: String },
category: { type: String },
price: { type: String },
size: { type: String },
color: { type: String },
thumbnail: { type: String },
qty: { type: Number },
},
],
// subTotal: { type: Number, required: true },
total: { type: Number, required: true },
shipping: { type: Object, required: true },
deliveryStatus: { type: String, default: "pending" },
paymentStatus: {
type: String,
required: true,
},
},
{
timestamps: true,
}
);
const Order = mongoose.model("Order", orderSchema);
export default Order;
I have some orders created by different users in my database. Now i am trying to get those specific orders associated with currently logged in user.
order.controller.js
export const getAllOrders = async (req, res) => {
const { _id } = req.user;
// console.log(typeof id);
try {
const orders = await Order.find({userId: _id});
console.log(orders);
res.status(200).json({ orders });
} catch (error) {
res.status(500).json({ msg: error.message });
}
};
I have tried this one but it always return an empty array.
Backend Code:
This is orderModel.js
import mongoose from "mongoose";
const orderSchema = mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
orderItems: [
{
name: { type: String, required: true },
qty: { type: String, required: true },
image: { type: String, required: true },
price: { type: String, required: true },
productId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Product",
},
},
],
deliveryAddress: {
address: { type: String, required: true },
area: { type: String, required: true },
// gender: { type: String, required: true },
postalCode: { type: String, required: true },
district: { type: String, required: true },
division: { type: String, required: true },
country: { type: String, required: true, default: "Bangladesh" },
},
paymentMethod: {
type: String,
required: true,
},
paymentStatus: {
id: { type: String },
status: { type: String },
update_time: { type: String },
email: { type: String },
},
taxPrice: {
type: Number,
required: true,
default: 0.0,
},
deliveryCost: {
type: Number,
required: true,
default: 0.0,
},
totalPrice: {
type: Number,
required: true,
default: 0.0,
},
discount: {
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);
export default Order;
This is orderController.js -
import asyncHandler from "express-async-handler";
import Order from "../models/orderModel.js";
// review: desc => Create New Order
// review: route => POST api/orders
// review: access => Private
const createOrder = asyncHandler(async (req, res) => {
const {
orderItems,
deliveryAddress,
paymentMethod,
taxPrice,
deliveryCost,
discount,
totalPrice,
} = req.body;
if (orderItems && orderItems.length === 0) {
res.status(400);
throw new Error("No order items");
} else {
try {
const order = new Order({
orderItems,
user: req.user._id,
deliveryAddress,
paymentMethod,
taxPrice,
deliveryCost,
discount,
totalPrice,
});
console.log("ORDER CREATED", order);
const createdOrder = await order.save();
console.log("ORDER saved", createdOrder);
res.status(201).json(createdOrder);
} catch (error) {
res.status(400);
throw new Error("Invalid order data", error);
}
}
});
// review: desc => GET order by id
// review: route => GET api/orders/:id
// review: access => private
const getOrderById = asyncHandler(async (req, res, next) => {
const order = await Order.findById(req.params.id).populate(
"user",
"name email"
);
if (order) {
res.json(order);
} else {
res.status(404);
throw new Error("Order not found");
}
});
export { createOrder, getOrderById };
Frontend Code:
const handleSubmit = (e) => {
e.preventDefault();
dispatch(
createOrder({
orderItems: cartItems,
deliveryAddress: addressObject,
paymentMethod,
taxPrice: vat,
deliveryCost,
discount,
totalPrice,
})
);
};
Here When I am sending request to backend, It's giving me validation error. As - orderItems.0.productId: Path productId is required. Why I am getting this error ? mongoose should not map data and get productId from sent cartItems, where is a field is _id ? Your time and help is most appreciated, Thanks.
I've been trying updateOne, findOneAndUpdate, and update. Nothing has worked. findOne() operation returns the correct documents.
userProfileModel.updateOne(
{ userEmail },
{
$push: {
userFavLocation: payload,
},
},
(err, result) => {
console.log(err);
console.log(result);
}
);
I get this but no change in my document.
{ ok: 0, n: 0, nModified: 0 }
userEmail and payload have the correct value. When I do findOneAndUpdate, it returns correct document but won't push the value.
This is the Schem for the user profile
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserProfileSchema = new Schema(
{
userEmail: {
type: String,
required: true,
unique: true,
},
userProfilePictureUrl: {
type: String,
},
userSignUpDate: {
type: Date,
},
userId: {
type: String,
required: true,
unique: true,
},
userFirstName: {
type: String,
required: true,
},
userLastName: {
type: String,
required: true,
},
userGender: {
type: String,
required: true,
},
userBirthday: {
type: Date,
required: true,
},
userCoordinates: {
type: {
type: String,
default: 'Point',
},
coordinates: {
type: [Number],
},
},
userFavFacilities: {
type: Object,
},
userHometown: {
address: Object,
},
userContact: {
friends: Object,
},
userOrganizations: {
organizations: Object,
},
userMessages: {
type: Object,
},
userAlerts: {
type: Object,
},
userRoles: Object,
userFacilities: Object,
},
{ collection: 'userprofilemodels' }
);
UserProfileSchema.index({ location: '2dsphere' });
module.exports = UserProfile = mongoose.model(
'userprofilemodels',
UserProfileSchema
);
You have to add the userFavLocation field to your schema or mongoose won't perform the update.
const UserProfileSchema = new Schema(
{
userEmail: {
type: String,
required: true,
unique: true,
},
userFavLocation: [PUT_ARRAY_ITEM_TYPE_HERE],
...
}
}
This is my schema...How can I push an element in an array of an array?
example: I've to insert an element in (patient.problems.feedback) in an already existing document. please help me how to code in node js-MongoDB
let Patient = new Schema({
patient: {
patientId: {
type: String,
required: false
},
name: {
type: String,
required: true
},
age: {
type: String,
required: true
},
gender: {
type: String,
required: true
},
city: {
type: String
},
phoneNumber: {
type: String,
min: 10,
max: 10
},
referredBy: {
type: String
},
createdAt: {
type: String
}
},
Problems: [{
problemId: {
type: String,
required: false
},
problem: {
type: String,
required: true
},
howLongSuffered: {
type: String
},
medicinesFollowed: {
type: String
},
createdAt: {
type: String
},
feedbacks: [{
feedbackId: {
type: String,
required: false
},
feedback: {
type: String,
required: false
},
updatedAt: {
type: String
}
}]
}]
})
**This is my controller
How can I update the existing document by pushing an element into the feedbacks
**
exports.addFeedbackDetailsForExistingProblem = async function(req, res) {
try {
let feedbackCreatedDate = new Date();
feedbackCreatedDate = feedbackCreatedDate.toDateString();
await patientModel.findById(req.params.id).then(async(result) => {
console.log(result + req.body.id);
await result.updateOne({ 'Problems._id': req.body.id }, {
$push: {
'Problems.feedbacks': {
'feedbacks.feedback': req.body.feedback,
'feedbacks.createdAt': feedbackCreatedDate
}
}
})
});
} catch (err) {
res.status(500).send("Something Went Wrong");
}
}