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);
}
Related
I'm using mongoose-paginate-v2 for my TransactionModel.
I can't seem to filter by the user name or email.
If I don't use any query the docs return with the populated objects, like the user's name, and email, so I believe the issue is with the filter variable.
I want to keep using mongoose-paginate-v2
const transactionSchema: Schema = new Schema(
{
user: { type: Types.ObjectId, ref: CollectionNames.user, required: false },
subscription: { type: Types.ObjectId, ref: CollectionNames.subscription, required: false },
paidAt: { type: Date, required: true, default: new Date() },
amount: { type: Number, required: true },
currency: { type: String, required: true, default: CurrencyCodes.USD },
status: { type: String, required: true, default: TransactionStatuses.pending },
refundedAt: { type: Date, required: false },
refundAmount: { type: Number, required: false },
provider: { type: String, required: true },
providerTransactionId: { type: String, required: true },
invoiceLink: { type: String, required: false },
referral: { type: referralSchema, required: false },
eventsHistory: { type: [String], required: false, default: [] }
},
{
timestamps: true
}
);
// The function body:
const { page, limit, query: searchQuery } = query;
const options = {
page: page || 1,
limit: limit || 10,
sort: {
createdAt: -1
},
populate: [
{
path: 'user',
select: 'name socialAccounts email lastLoginEmail notificationEmail'
},
{
path: 'referral',
select: 'user commission payoutExpectedAt paidAt status'
}
],
lean: true
};
const filter = {};
if (searchQuery) {
const searchQueryRegex = new RegExp(searchQuery, 'i');
Object.assign(filter, {
$or: [
{
providerTransactionId: {
$regex: searchQueryRegex
}
},
{
'user.name': {
$regex: searchQueryRegex
}
},
{
'user.email': {
$regex: searchQueryRegex
}
},
]
});
}
const { docs, totalDocs, totalPages, hasNextPage } = await TransactionModel.paginate(filter, options);
I am creating a search API and using the $regex operator of MongoDB to filter from search text. But I also want to add a category inside the $or operator. I have a category Id and this is an id of another collection whenever I want to get the category I have to populate the category id. But I want to use the same $regex operator on the category as given below.
Category Schema
const mongoose = require('mongoose');
const categorySchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
slug: {
type: String,
required: true,
unique: true
},
type: {
type: String
},
categoryImage: {
type: String
},
parentId: {
type: String
}
}, {
timestamps: true
})
module.exports = mongoose.model('Category', categorySchema);
Product Shema
const mongoose = require("mongoose");
const productSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
trim: true,
},
slug: {
type: String,
required: true,
unique: true,
},
price: {
type: Number,
required: true,
},
quantity: {
type: Number,
required: true,
},
description: {
type: String,
required: true,
trim: true,
},
offer: {
type: Number,
},
productPictures: [{ img: { type: String } }],
views: {
type: Number,
min: 0,
default: 0,
required: true
},
ratings: [
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
rate: {
type: Number,
required: true,
max: 5,
},
reviewTitle: {
type: String,
},
review: {
type: String,
},
reviewImages: [
{
img: String,
},
],
date: {
type: Date,
required: true,
}
},
],
category: {
type: mongoose.Schema.Types.ObjectId,
ref: "Category",
required: true,
},
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
},
{
timestamps: true,
}
);
module.exports = mongoose.model("Product", productSchema);
Search Product Controller
exports.searchProducts = async (req, res) => {
try {
const { page = 1, limit = 20 } = req.query;
const pagination = {
skip: (Number(page) - 1) * Number(limit),
limit: Number(limit),
};
const search = req?.query?.s?.split("+").join("") || "";
const fields = req?.query?.fields?.split(",").join(" ");
const sort = req?.query?.sort?.split(",")?.join(" ");
const { products, matchCount, pageNeeded, showingFrom, showingTo } =
await searchProductsService(search, fields, sort, pagination);
if (products.length === 0) {
return res.status(400).json({ error: "No products found" });
}
res
.status(200)
.json({ products, matchCount, pageNeeded, showingFrom, showingTo });
} catch (error) {
return res.status(400).json({ error: "Something Wen't wrong" });
}
};
Search Product Service (Where I am doing database opearations)
exports.searchProductsService = async (search, fields, sort, pagination) => {
await SearchQuery.updateOne(
{ title: search },
{ $inc: { searchedCount: 1 } },
{ upsert: true }
);
const query = {
$or: [
{ name: { $regex: search, $options: "i" } },
{ description: { $regex: search, $options: "i" } },
],
};
const products = await Product.find(query)
.skip(pagination.skip)
.limit(pagination.limit)
.select(fields || "name productPictures price")
.sort(sort);
const matchCount = await Product.find(query).count();
const pageNeeded = Math.ceil(matchCount / pagination.limit);
const showingFrom = pagination.skip + 1;
const showingTo = pagination.skip + products.length;
return { products, matchCount, pageNeeded, showingFrom, showingTo };
};
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.
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
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
}
}
});