how sort with mongoose - javascript

I have a little question
I try to sort with mongoose I know the simple way
but I dont know how to do that with data I get in req.body lets say.
I add here a code I try
exports.sortBy = async (req, res, next) => {
const data1 = req.body.data1 //the data i want to sort
const sortBy = req.body.sortBy //sory by price,createdAt,length and more
const downUp = req.body.downUp // 1, -1
console.log(sortBy)
console.log(data1)
const data = await Book.aggregate([
{
$sort: { [sortBy]: downUp }
},
])
res.status(200).json({
status: 'success',
results: data.length,
data
})
}
so I can sort by the data I get in req.body

Try the following:
const data = await Book.sort({sortBy: downUp});
which seems to work and is much easier to read.

Related

Express js related articles - error cannot read properties of null

I try to show related articles based on categories. I use mongoose to query things from MongoDB.
When I try the code below, I get the error "TypeError: Cannot read properties of null (reading 'category')" but console.log from articlecategories first showing array with categories and then throw the error "cannot read"..
I'm a beginner in express js, maybe someone gives me a hint.
exports.articleDetail = async (req, res) => {
const article = await Article.findOne({ slug: req.params.slug }).populate('category').populate('author');
const articlecategories = article.category
categories = []
for(let i=0;i<articlecategories.length;i++){
const category = articlecategories[i]
categories.push(category._id)
}
console.log(categories)
const relatedarticles = await Article.find({ category : { $all : categories }})
console.log(article);
res.render('article', { article, relatedarticles })
}
Edit
Thank You all for answers. I have a solution. Problem is that when loop through article categories, I get no category ID but new ObjectId: new ObjectId("636bc1c64f7470f2557b61d7")
To let this work, I must use .toString() and get only Id and then push this Id to array.
This is working code:
exports.articleDetail = async (req, res) => {
const article = await Article.findOne({ slug: req.params.slug }).populate('category').populate('author');
categories = []
for(let i=0;i<article.category.length;i++){
const category = article.category[i]
const catid = category._id.toString()
categories.push(catid)
}
console.log(categories)
const articles = await Article.find({category: { $all: categories }}).populate('author')
res.render('article', { article, articles })
}
Probably your call to await Article.findOne just returns null since the object could not be found.
You should check if there is anything found and, if not, directly return an error like this:
exports.articleDetail = async (req, res) => {
const article = await Article.findOne({ slug: req.params.slug }).populate('category').populate('author');
if ( !article ) return res.status(404).json(/* include your error object here */);
const articlecategories = article.category
categories = []
for(let i=0;i<articlecategories.length;i++){
const category = articlecategories[i]
categories.push(category._id)
}
console.log(categories)
const relatedarticles = await Article.find({ category : { $all : categories }})
console.log(article);
res.render('article', { article, relatedarticles })
}

How would I properly set a new variable for a json object?

In Node JS I have an endpoint where I am trying to get data from two different mongo collections and when trying to piece the data together I am not able to add another property to the JSON object.
const getLessonWithTopics = async (req, res) => {
const lessonId = req.params.id;
// Get the lesson
Lesson.findOne({_id: lessonId}).exec((err, data) => {
let lesson = data;
Topic.find().where('_id').in(data.topics).exec((err, topics) => {
if(err) res.status(500).send("Error something went wrong");
lesson.associatedTopics = topics;
console.log(lesson);
res.json(lesson)
})
})
}
When logging lesson to console it does not have the associatedTopics property even though through searching online I have found multiple instances where some is saying this is how you would add this property. (Ex. Add new attribute (element) to JSON object using JavaScript )
I have tried using var as well, to see if that would change something (maybe make it mutable) it did not.
** When logging the topics object to console it does log the data that I expected so the variable 'topics' is not the issue **
I'm sure that it is something simple that I am missing and hoping someone with a large brain can help figure this out for me.
Any help would be appreciated, Thank you!
Can you try once with the following code?
const getLessonWithTopics = async (req, res) => {
const lessonId = req.params.id;
// Get the lesson
try {
const lession = await Lession.findOne({ _id: lessonId }).lean()
const topics = await Topic.find({ _id: { $in: lession.topics } }).lean()
lession.associatedTopics = topics
res.json(lesson);
} catch (err) {
console.log(err)
res.status(500)
}

How to make variables accessible across multiple get requests in express? And is there a better way to code this?

I have the following get request where I call a bunch of data and pass it through to my EJS view.
router.get('/currentrentals', ensureAuthenticated, async (req, res) => {
const companies = await Company.getCompanies();
const barges = await Barge.getBarges();
const parishes = await Parish.getParishes();
const states = await State.getStates();
const pickupdropoff = await PickupDropoff.getPickupDropoff();
var notifications = await Notification.getNotifications();
JSON.stringify(barges);
JSON.stringify(companies);
JSON.stringify(parishes);
JSON.stringify(states);
JSON.stringify(pickupdropoff);
JSON.stringify(notifications);
var notifications = await notifications.sort((a, b) => b.id - a.id).slice(0,3);
res.render('currentrentals', {
name: req.user.name, companies: companies, barges: barges, parishes: parishes, states: states, pickupdropoff : pickupdropoff, notifications : notifications
});
}
);
Two questions:
I have multiple get requests that requires the same information. Is there a way to make this data available across the entirety of my site, so I don't have to rewrite this for each get path?
Is there a more succinct way to write the existing code I have? Perhaps looping through them or something of the sort? Simply for learning purposes.
The code currently works as-is.
Thanks!
If the data is constant, you can try this:
let data = null;
async function getData() {
if (!data) {
data = {
companies: await Company.getCompanies(),
barges: await Barge.getBarges();
parishes: await Parish.getParishes(),
states: await State.getStates(),
pickupdropoff: await PickupDropoff.getPickupDropoff(),
notifications: (await Notification.getNotifications()).sort((a, b) => b.id - a.id).slice(0,3)
};
}
return data;
}
router.get('/currentrentals', ensureAuthenticated, async (req, res) => {
res.render('currentrentals', { name: req.user.name, ...(await getData()) });
}
);
// other routes

How to use the findOne mongoDB query correctly?

My goal is to get the one product object back depending on the product id i marked in green (out of the whole products array in my mongo DB)
My Backend entry looks as follows:
router.get("/:id", async (req, res)=> {
const mid=req.params.id;
console.log(mid)
const products = await Product.findOne({ id: mid })
console.log(products)
if (products) {
res.send(products);
} else {
res.status(404).send({message:"product not found"})
}
});
Connsole.log(mid) on line three works and it gives the right id back. However when i try to filter that one array depending on the value in line three i always get back the first object of my Database, which is the gopro camera, instead of the right object.
The Output looks as Follows:
632834528
{
_id: '5f9849daf641a82b257d529b',
id: 3484,
agentId: 66343,
title: 'GoPro Camera',
slug: 'gopro',
What am i doing Wrong?
I tried const products = await Product.find({ id: mid }) as well, but it gives me the whole array back instead of just the one object.
I think it's returning a Query. Try:
const products = await Product.findOne({ id: mid }).exec();
This solution worked for me:
I have to use the Expressasynchandler like this:
Edit: This solution might not be the best (see comments on answer above)
router.get("/:id", expressAsyncHandler(async (req, res) => {
const mid=req.params.id;
const products = await Product.findOne({ id: mid })
if (products) {
res.send([products]);
} else {
res.status(404).send({message:"product not found"})
}
}));

Next.js & MongoDB (without Mongoose) returning empty array

I'm using API routes in Next.js with sample data from MongoDB. I am trying to return the data from a single object. First time working with MongoDB, so apologies if the answer has been staring me in the face.
I'm getting an empty array returned with the following query:
import { connectToDatabase } from '../../../util/mongodb';
export default async (req, res) => {
const { db } = await connectToDatabase();
const movies = await db
.collection("movies")
.find({ "_id": "573a1395f29313caabce1f51" })
.limit(20)
.toArray();
res.json(movies);
};
Which corresponds to an object like this:
{
"_id": "573a1395f29313caabce1f51",
"fullplot": "some text goes here"
}
What am I missing? Shouldn't .find({_id: "573a1395f29313caabce1f51"}) return that information? Why am I only seeing an empty array? I understand why it's returning an array (I added .toArray()), but that shouldn't impact whether the results are returned or not.
For what it's worth, querying without parameters works properly. No issues with this query:
import { connectToDatabase } from '../../util/mongodb';
export default async (req, res) => {
const { db } = await connectToDatabase();
const movies = await db
.collection("movies")
.find({})
.sort({ metacritic: -1 })
.limit(20)
.toArray();
res.json(movies);
};
Any help is appreciated, thanks in advance!
Needed to cast to an objectID as mentioned in the comments.
https://docs.mongodb.com/manual/reference/operator/aggregation/toObjectId/

Categories

Resources