can't get the user's address in mongoose / nodejs - javascript

When the app loads it fetches initialData Array of objects from the backend where I have all the info I need, like categories,orders,products etc. Inside the orders array i have all the info about the users ordered items, status etc. I want to load the users address, when he filled up the address form that address.I have that address stored inside address.js-> UserAddress model/schema. So I want to load the users address inside orders array.
plz help me get the users address inside the orders array so that i can display the users address inside my admin-app->orders card, i'm new at this so I'm unable to figure it out on my own.
here is my orderSchema
const orderSchema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
addressId: {
type: mongoose.Schema.Types.ObjectId,
ref: "UserAddress.address",
required: true,
},
totalAmount: {
type: Number,
required: true,
},
items: [
{
productId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Product",
},
payablePrice: {
type: Number,
required: true,
},
purchasedQty: {
type: Number,
required: true,
},
},
],
paymentStatus: {
type: String,
enum: ["pending", "completed", "cancelled", "refund"],
required: true,
},
paymentType: {
type: String,
enum: ["cod", "card"],
required: true,
},
orderStatus: [
{
type: {
type: String,
enum: ["ordered", "packed", "shipped", "delivered"],
default: "ordered",
},
date: {
type: Date,
},
isCompleted: {
type: Boolean,
default: false,
},
},
],
},
{ timestamps: true }
);
module.exports = mongoose.model("Order", orderSchema);
here is my address schema:
const addressSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
min: 3,
max: 50,
},
mobileNumber: {
type: String,
required: true,
trim: true,
},
pinCode: {
type: String,
required: true,
trim: true,
},
locality: {
type: String,
required: true,
trim: true,
min: 10,
max: 100,
},
address: {
type: String,
required: true,
trim: true,
min: 10,
max: 100,
},
cityDistrictTown: {
type: String,
required: true,
trim: true,
},
state: {
type: String,
required: true,
required: true,
},
landmark: {
type: String,
min: 10,
max: 100,
},
alternatePhone: {
type: String,
},
addressType: {
type: String,
required: true,
enum: ["home", "work"],
required: true,
},
});
// B
const userAddressSchema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
address: [addressSchema],
},
{ timestamps: true }
);
mongoose.model("Address", addressSchema);
module.exports = mongoose.model("UserAddress", userAddressSchema);
here is the get initial data where i get all the data/response:
exports.initialData = async (req, res) => {
const categories = await Category.find({}).exec();
const products = await Product.find({ createdBy: req.user._id })
.select("_id name price quantity slug description productPictures category")
.populate({ path: "category", select: "_id name" })
.exec();
const orders = await Order.find({})
.populate("items.productId", "name")
.exec();
res.status(200).json({
categories: createCategories(categories),
products,
orders,
});
};
here is the response of initial data:

You can simply use the $lookup aggregation from the order schema to the address schema to fetch the address of the user via the user field.
More info on MongoDb $lookup aggregation here

Related

how can obtain a reverse populate in two models of mongosee

hi i have this mongose models
new mongoose.Schema({
type_order: {
type: String,
required: true,
},
article: {
required: true,
type: [{
id: {type: mongoose.Schema.Types.ObjectId, ref: 'product'},
type_article: String,
quanty: Number,
}],
},
status: {
required: true,
type: String,
},
profile_id: {
required: true,
type: mongoose.Schema.Types.ObjectId,
ref: 'customer',
},
}, {timestamps: true});
module.exports = mongoose.model('order', dataSchema);
const dataSchema = new mongoose.Schema({
profile_id: {
type: String,
required: true,
},
title_lower: {
required: true,
type: String,
},
title: {
required: true,
type: String,
},
category_id: {
required: true,
type: String,
},
status: {
required: true,
type: String,
},
brand: {
required: true,
type: String,
},
description: {
required: true,
type: String,
},
stock: {
required: true,
type: Number,
},
price: {
required: true,
type: Number,
},
discount: {
required: true,
type: Number,
},
images: {
type: [{
url: String,
first: Boolean,
}],
},
}, {timestamps: true});
module.exports = mongoose.model('product', dataSchema);
I am trying to obtain the orders that have in their article field an article or several that belong to the profile id of the product that would be the person who published that product.
I am currently doing it bringing all the orders for the person's products but I know that it is not the most optimal way to do it and in the long run the performance will be affected.
i am trying something like this:
const profile = await customer.findOne({userId: req.user.id});
if (profile) {
// eslint-disable-next-line max-len
const articles = await Product.find({profile_id: profile._id});
const response=[];
const preresponse=[];
for (let index = 0; index < articles.length; index++) {
const element = articles[index];
const orders= await getOrdersByArticleId(element._id, res);
preresponse.push({
'article_id': element._id,
'title': element.title,
'price': element.price,
'stock': element.stock,
orders,
});
articles[index].orders = orders;
}
preresponse.forEach((art)=> {
art.orders.forEach((order)=>{
console.log(order);
const result = response.find(({order_id}) => order_id == order.order_id); ;
console.log(result);
if (result) {
console.log('holaa');
} else {
response.push({
'order_id': order.order_id,
'type': order.type_order,
'status': order.status,
'date': order.date.toDateString(),
'articles': [{'product_id': order.article_id,
'quanty': order.quanty}],
});
}
});
});
return res.status(200).json(articles);
}

How to get only matched data in mongoose (node.js)?

I am building a bus ticket booking app in node.js. I want to fetch only related data about queries not all the data But I am getting all the data about Bus.
Here is the location model. only admin can enter data about locations.
const locationSchema = new mongoose.Schema(
{
departureLocation: {
name: {
type: String,
required: true,
lowercase: true
},
time: {
type: String,
required: true,
},
subLocations: { type: [String], lowercase: true },
},
arrivalLocation: {
name: {
type: String,
required: true,
lowercase: true
},
time: {
type: String,
required: true,
},
subLocations: { type: [String], lowercase: true },
},
},
{
timestamps: true,
}
);
Here is the route table. Again admin...
const routeSchema = new mongoose.Schema({
location:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Location',
required: true
},
duration: {
type: Number,
required: true
},
date: {
type:String,
required: true
},
},
{
timestamps: true,
});
Bus model: Admin...
const busSchema = new mongoose.Schema({
busNumber: {
type: String,
unique: true,
required: true,
},
seats: {
type: Number,
},
route: {
type: mongoose.Schema.Types.ObjectId,
ref: "Route",
required: true,
},
},
{
timestamps: true,
});
and here finally the booking table:
const bookingSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
busId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Bus",
required: true,
},
passengers: [
{
name: { type: String, required: true, trim: true },
gender: { type: String, required: true, trim: true },
age: { type: Number, required: true, trim: true },
}],
phone: {
type: Number,
required: true,
},
email: {
type: String,
required: true,
},
bookingDate: {
type: String,
required: true,
},
fare: {
type: Number,
required: true,
},
seats: {
required: true,
type: [Number],
},
departureDetails: [
{
city: { type: String, required: true, trim: true },
location: { type: String, required: true, trim: true },
time: { type: String, required: true, trim: true },
date: { type: String, required: true, trim: true },
},
],
arrivalDetails: [
{
city: { type: String, required: true, trim: true },
location: { type: String, required: true, trim: true },
time: { type: String, required: true, trim: true },
date: { type: String, required: true, trim: true },
},
],
},{
timestamps:true
});
Whenever an authorized user enters the booking data It is getting saved to the database. No problem whatsoever
Now I want to show every user(Non-authorized as well) of my app about trips(routes), the bus which will run on that particular trip and reserved and available seats in that particular bus which is currently stored.
But the problem is that I am getting all the buses even if it is not on that trip.
here is the query:
router.get("/trip/single", async (req, res) => {
if (!req.query.departure || !req.query.arrival || !req.query.date) {
return res.send({
error: "Please enter the data to get the trip",
});
}
const { departure, arrival, date } = req.query;
let locations = await Location.find({
'departureLocation.name': departure,
'arrivalLocation.name': arrival,
});
const ids = locations.map(location => location._id)
const routes = await Route.find({$and: [{location : {$in: ids}},{date}]});
const route = routes.find(()=>{
return ([{ date }, { routes }])
});
let buses = await Bus.find({})
let matchedBuses = buses.filter((bus)=> {
return bus.routes === locations._id
})
const bookings = await Booking.find({})
const busIdWithSeatsObj = {}
for(let i = 0; i < matchedBuses.length; i++){
let currentBusSeats = []
const busBookings = bookings.filter((booking) => {
return (booking.departureDetails.date === date &&
booking.busId.toString() === matchedBuses[i]._id.toString()
)
})
busBookings.forEach((booking) => {
currentBusSeats = [...currentBusSeats, ...booking.seats]
})
busIdWithSeatsObj[matchedBuses[i].seats] = currentBusSeats
}
res.status(200).send({route, matchedBuses, busIdWithSeatsObj});
});
Now I also want to fetch details by Id(only single bus).
How to do that?
Can anyone help me out here?
here's the input data image with result for date: 2022-06-02 which is actually available in the database : https://i.stack.imgur.com/FlfaG.png
This is the second query with result for date: 2022-06-01. It is not available in the database still showing matchedBus.: https://i.stack.imgur.com/xY5pW.png Now route data is gone but matched buses still shows.

Ignore key if empty value

I'm creating a mongoose entry, and this is my schema:
const OrdersSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "Users",
required: true,
},
currency: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
rate: {
type: Number,
required: true,
},
amount: {
type: Number,
required: true,
},
coupon: {
type: mongoose.Schema.Types.ObjectId,
ref: "Coupons",
},
subtotal: {
type: Number,
required: true,
},
total: {
type: Number,
required: true,
},
recipient: {
type: mongoose.Schema.Types.ObjectId,
required: true,
},
status: {
type: String,
required: true,
default: "On-hold",
},
payment: {
type: Object,
required: true,
},
shortId: {
type: String,
required: true,
},
createdAt: {
type: Date,
default: Date.now,
required: true,
},
});
Coupon is optional. The code to create a new order is:
const order = await Orders.create({
user: req.id,
currency: body.selectedCountry,
country: body.selectedCountry,
rate: rate.rates[body.selectedCountry],
amount: body.amount,
coupon: body.coupon.code,
subtotal: body.subtotal,
total: body.total,
recipient: body.recipient,
payment: body.paymentData,
shortId: shortid.generate(),
});
However, when coupon is an empty string I get a MongooseError [CastError]: Cast to ObjectID failed for value "" at path "coupon"
I need to remove this key and value from the object creation, when creating the order.
How can I remove this key if coupon code is empty?
Thanks in advance
The issue is you are trying to fit an empty string value in the data-type objectID.
A possible solution to this is to use below condition in your code:
coupon: body.coupon.code ? body.coupon.code : null
This will set coupon to null in case body.coupon.code is "".

mongo query $near always 0 results

My search Position is the same as the position in the database. The result is an empty array. I expected to get the one element from database, because the distance between both locations is 0.
Mongo Doku $near
Query to find all nearest
Request.find({
address: {
location: {
$near: {
$geometry: {
type: 'Point' ,
coordinates: [8.4821159,49.4705199],
},
$maxDistance: 10000,
$minDistance: 0,
},
},
},
})
Mongoose Model
Edit (add): this.request.index({'address.location': '2dsphere'});
import mongoose from 'mongoose';
const ObjectId = mongoose.Schema.Types.ObjectId;
import {RequestMiddleware} from './RequestMiddleware';
class Request extends mongoose.Schema {
public request: mongoose.Schema;
constructor() {
const RequestSchema = {
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
category: {
type: ObjectId,
ref: 'Category',
required: true,
},
created_by: {
type: ObjectId,
ref: 'User',
required: true,
},
address: {
location: {
type: {
type: String,
enum: ['Point'],
default: 'Point',
required: true,
},
coordinates: {
type: [Number],
default: [0, 0],
required: true,
},
},
plz: {
type: String,
required: false,
},
city: {
type: String,
required: false,
},
street: {
type: String,
required: false,
},
street_nr: {
type: String,
required: false,
},
},
time_end: {
type: Date,
required: false,
},
confirmed_helper: {
type: ObjectId,
ref: 'User',
},
helper: [{
helperId: {
type: ObjectId,
ref: 'User',
},
offer_text: {
type: String,
},
}],
};
const request = super(RequestSchema, {
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at',
},
});
this.request = request;
this.request.index({'address.location': '2dsphere'});
this.request.plugin(RequestMiddleware);
return this.request;
}
}
export default mongoose.model('Request', new Request());
Database:
You need two things:
2dspere index (probably you already have it):
db.col.createIndex( { "address.location" : "2dsphere" } )
and to modify your query so that it uses the dot notation instead of nested object:
let result = await Request.find({
'address.location': {
$near: {
$geometry: {
type: 'Point',
coordinates: [8.4821159, 49.4705199]
},
$maxDistance: 10000,
$minDistance: 0
}
}
});

Keystonejs: custom names to defaultColumns of Admin UI

I use keystonejs as Node.js CMS
Model look like this:
Message.add({
uId: { type: String, initial: true, required: true },
title: { type: String, initial: true, required: true },
createdDate: { type: Date, default: Date.now, required: true },
user: {
name: { type: Types.Relationship, ref: 'User', initial: true, required: true },
email: { type: Types.Relationship, ref: 'User', initial: true, required: true }
},
status: {
display_name: { type: String, initial: false, required: true },
state: { type: String, initial: false, required: true }
}
})
Message.defaultColumns = 'user.name, title, status.display_name'
Message.register();
Titles of the columns in the generated Admin UI looks like this:
User Name,
Title
Status Display_name
Is it possible to set custom names to defaultColumns to make it look better?
You can add the label property to your field options. The label is used as label for the field and as column name.
For example:
display_name: { type: String, initial: false, required: true, label: 'Whatever you like' }

Categories