How to use the findOne mongoDB query correctly? - javascript

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"})
}
}));

Related

how sort with mongoose

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.

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/

Searching Multiple parts of a Mongodb model

This is my search route:
router.get("/search", async (req, res)=>{
let search = {}
if(req.query.q !=null && req.query.q!==""){
search.title = new RegExp(req.query.q, "i")
search.description = new RegExp(req.query.q, "i")
}
try{
console.log(search)
const posts = await Post.find(search)
res.render("posts/search", {posts: posts, search: req.query})
}catch(err){
console.log(err)
}
})
When I send my query like this, my console returns me this value:
{ description: /whateverIamsearchingfor/i, tags: /whateverIamsearchingfor/i }
And when I search only one of them and comment out the other line I get this: (no surprises)
{ description: /whateverIamsearchingfor/i}
Naturally, It works when only I search for either titles or descriptions. How do I fix this? I want to be able to make a search on both of these parts of this model at the same time. (or maybe even search the other parts as well)
Yay. I made it. In case anybody is still wondering how, I'll post it here:
const posts = await Post.find({ "$or": [
{ title: search.title },
{ description: search.description }
] });
Works like a charm now.

Sequelize join on where condition returned from first table or return object values in an array derrived from foreach coming up empty

I've been trying to figure out this for a while now so any help would be very much appreciated.
I have one table called Interaction that searches with the client user's id and returns all interactions where they are the target user. Then I want to return the names of those users who initiated the interaction through the User table.
I tried using include to join the User table but I can't get the user's names using the where clause because it is based on a value returned in the first search of the Interaction table and don't know if I can search on a value that isn't the primary key or how?
The closest I've gotten is to use foreach and add the users to an array but I can't get the array to return in my response, because outside of the loop it is empty. I've tried suggestions I've found but can't figure out how to return the array outside of the foreach, if this is the best option. I am sure it is something really stupid on my behalf. TIA.
This is my attempt at include function:
getInvited: (req, res, next) => {
var user = {}
user = req.user;
let usrId = user[0]['facebookUserId'];
var userObjArray = [];
Interaction.findAll({
where: {
targetUserId: usrId,
status: 'invited',
},
include: [{
model: User,
attributes: [
'firstName'
],
where: {
facebookUserId: IwantToJoinOnInteraction.userId // replace with working code?
}]
}).then(function (users) {
res.send(users);
}).catch(next);
}
Or my attempt at foreach:
getInvited: (req, res, next) => {
var user = {}
user = req.user;
let usrId = user[0]['facebookUserId'];
var userObjArray = [];
Interaction.findAll({
where: {
targetUserId: usrId,
status: 'invited',
}
}).then(function (interactions) {
interactions.forEach((interaction) => {
User.findOne({
where: {
facebookUserId: interaction.userId // this is the where clause I don't know how to add in my first attempt with include
},
attributes: ['firstName', 'facebookUserId']
}).then(function (user) {
userObjArray.push(user['dataValues']);
console.log(userObjArray); // on the last loop it contains everything I need
})
})
res.status(200).send(userObjArray); // empty
}).catch(next);
},
You have to wait for all promises before sending the response. Your code runs async. With the forEach you are calling User.findOne async but you don't wait for all User.findOne to finish. A convenient way to make this work is Promise.all. You can pass an array of promises and the returned promise resolves to an array of all the resolved promises.
Promise.all(interactions.map(interaction => User.findOne(...)))
.then(users => {
res.status(200).send(users.map(user => user.dataValues))
})
You could write this much more easy to read woth async/await
getInvited: async (req, res, next) => {
...
const interactions = await Interaction.findAll(...)
const users = await Promise.all(interactions.map(interaction => User.findOne(...)))
res.status(200).send(users.map(user => user.dataValues))
}

How can i save results from mongoose query to a variable

I'm trying to save some objects into an array by looping through a list of songs in an album, looking for relevant songs and trying to save into array for later use. is there any way to achieve this?
I need some explanation using mongoose.
exports.playlistPlayer = function (req, res, next) {
Playlist.findById({
_id: req.body.playlist._id
}, (err, playlist) => {
var customAlbum = []; //This variable it's inside the same block i believe
playlist.songs.forEach(function (song) {
Song.findById({
_id: song.song_id
}, (err, songs) => {
var customSong = {
title: songs.title,
time: songs.time,
source: songs.source,
song_id: songs._id
}
customAlbum.push(customSong)
console.log(customAlbum) //it works here
});
});
console.log(customAlbum) //it returns an empty array here where i need the data
});
};
The problem is that the findById method is also asynchronous. I recommend you to learn about promises in javascript. One possible solution would be using the async/await feature from ES7:
// asynchronous function
exports.playlistPlayer = async (req, res, next) => {
// wait for the findById method promise to resolve
const playlist = await Playlist.findById({
_id: req.body.playlist._id
})
// wait for finding all songs in db whose id's are in
// the playlist.songs array
const songs = await Song.find({
_id: { $in: playlist.songs }
})
// create the customAlbum by using the map method to
// tramsform the song objects to the required form
const customAlbum = songs.map(song => ({
title: song.title,
time: song.time,
source: song.source,
song_id: song._id
}))
// and there you should now have your customAlbum array
console.log(customAlbum)
// now you can use it for example
// to return a response to the client:
// res.json(customAlbum)
}

Categories

Resources