I'm trying to get and display all entries in an 'item' collection that contain and are listed by a user/userID from a user collection.
item_controller.js:
const Item = require('../models/item_schema')
const getUserItems = (req, res) => {
Item.findById(req.params.userID).populate('categoryID').populate('qualityID').populate('userID')
.then((data) => {
if (data) {
res.status(200).json(data)
} else {
res.status(404).json(`Item from user id ${req.params.userID} not found.`)
}
})
}
module.exports = {
getUserItems
}
item_schema.js:
const { Schema, model} = require('mongoose')
const itemSchema = new Schema({
title: {
type: String,
required: [true, 'Title field is required.']
},
description: {
type: String,
required: [true, 'Description field is required.']
},
userID: {
type: Schema.Types.ObjectId,
ref: "User",
required: [true, 'User field is required']
},
categoryID: {
type: Schema.Types.ObjectId,
ref: "Category",
required: [true, 'Category field is required']
},
qualityID: {
type: Schema.Types.ObjectId,
ref: "Quality",
required: [true, 'Quality field is required']
},
price: {
type: Number
},
claimed:{
type: Boolean
}
}, {
timestamps: true
})
module.exports = model('Item', itemSchema)
server.js:
const express = require('express')
const cors = require('cors')
const jwt = require('jsonwebtoken')
require('dotenv').config()
require('./db')()
const { getUserItems } = require('./controllers/item_controller')
const port = process.env.PORT || 3000
const app = express()
app.use(cors())
app.use(express.json())
app.use((req, res, next) => {
if (req.headers && req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
jwt.verify(req.headers.authorization.split(' ')[1], 'zero_waste_app', (err, decode) => {
if (err) req.user = undefined
req.use r = decode
next()
})
} else {
req.user = undefined
next()
}
})
// Item Routes
app.get('items/user/:userID', getUserItems)
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
I think my problem is in the item_controller, I've tried a few different ways, such as Item.find({userID: userID})
or even hardcoding a userID in Item.find({userID: '620a6299299db14c46a1eb9f'})
, but I can't get it to work. Does anyone know what I'm doing wrong and how I can fix it?
Also please do let me know if there's any more information or code I can give that would be helpful.
CodePudding user response:
So, first of all, if you don't specify the primary key, mongoose will automatically generate a _id
field in your collections. and this attribute is the one that is used in the "...ById" methods of the collection, like findById
, findByIdAndUpdate
, etc.
Ok, how it solves your problem? You're using Item.findById
method using the value of a userID
, but your _id
is completely different. You've to use the .find
method passing the userID
attribute, also you don't need to chain the populate
methods, you can populate many fields in only one method call.
Try to change your controller to this:
const {userID} = req.params;
Item
.find({userID})
.populate('categoryID qualityID userID')
.then((data) => {
if (data) {
return res.status(200).json(data)
}
return res.status(404).json(`Item from user id ${req.params.userID} not found.`)
})
CodePudding user response:
I figured it out.
const getUserItems = (req, res) => {
Item.find({userID: req.params.userID}).populate('categoryID').populate('qualityID')
.then((data) => {
if (data) {
res.status(200).json(data)
} else {
res.status(404).json(`Item from user id ${req.params.userID} not found.`)
}
})
}
also my route was missing a '/' at the beginning, so:
app.get('/items/user/:userID', getUserItems)
and not what I previosly had:
app.get('items/user/:userID', getUserItems)