i'm trying to get the _id field of specific employee by req.body.name :
const requestVacation = async (req, res) => {
try {
const employee = await Employee.find({ nameAR: req.body.name }).select('_id')
const vacation = new Vacation({
employeeId: employee._id,
type: req.body.type,
startDate: req.body.startDate,
endDate: req.body.endDate,
numberOfHours: req.body.numberOfHours,
});
await vacation.save();
res.status(200).json("vacation has been requested successfully");
} catch (err) {
console.log(err);
res.status(404).json(err);
}
};
the employee variable will return this :
[ { _id: new ObjectId("630ba65261c73f3c8afc5c8c") } ]
but i only want the _id value to save it as employeeId in vacation collection, so how can i get the _id value ?
i tried :
employee._id
but it returns undefined
i also tried :
const employee = await Employee.find({ nameAR: req.body.name }, { _id: 1 });
it returns the same result, how to get the _id value out of it
You are returning an array from the DB with find. You can access the _id with employee[0]._id or use findOne, and it will return an object to be accessed with employee._id
Related
I am trying to edit the whole form by using the updateOne function of mongoose but whenever I clicks the edit button, it shows error CastError: Cast to ObjectId failed for value "1" (type string) at path "_id" for model "Stocks".
counter.js
const counterSchema = {
id: {
type: String
},
seq: {
type: Number
}
}
stocks.js
const stockSchema = new Schema({
id: {
type: Number
},
flowerName: {
type: String,
required: true
}
},{timestamps: true }
);
This is from my post Method wherein I add a value to the form
Counter.findOneAndUpdate(
{id: "autoval"},
{"$inc":{"seq": 1}},
{new: true}, (err, cd) => {
let seqID;
if(cd==null) {
const newValue = new Counter({id: "autoval", seq:1})
newValue.save()
seqID = 1
} else {
seqID = cd.seq
}
const qty = Number(req.body.quantity)
const price = Number(req.body.pricePieces)
const stock = new Stocks ({
id: seqID,
flowerName: req.body.flowerName
})
stock.save()
.then(result => {
res.redirect('flowers-in-stock');
}).catch(err => console.log(err));
}
)
And I want to proceed in the edit page
Stocks.findById(req.params.id)
.then (stock => {
res.render('flowers-in-stock-edit', {stocks: stock})
}).catch(err => console.log(err));
}
The findById function matches its parameter with the _id field in the document in MongoDB.
Your schema defines id but not _id, so the _id will be automatically created on insert, and will be type ObjectId.
findById attempts to cast its parameter to match the datatype of the _id field. The error message indicates that you are passing "1" as the value to find, which findById is attempting to cast to ObjectId. "1" is not a valid ObjectId, so that fails.
To search based on your id field, use findOne instead of findById:
Stocks.findOne({id: req.params.id})
Im trying to create a list of items for each users, which means user can create items and ı want to keep that data for each user.
Which I create two different schemas for that in:
user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
userSchema = new Schema({
unique_id: Number,
email: String,
username: String,
password: String,
passwordConf: String,
teamname: String,
items: [{ type: Schema.Types.ObjectId, ref: 'Item' }],
});
(ItemSchema = new Schema({
createrId: { type: Schema.Types.ObjectId, ref: 'User' },
productname: String,
description: String,
price: String,
totalStock: String,
})),
(Item = mongoose.model('Item', ItemSchema));
User = mongoose.model('User', userSchema);
module.exports = { Item, User };
After creating 2 schemas ı used them in index.js that routers everything together.
index.js
router.get('/create_item', function (req, res, next) {
return res.render('items.ejs');
});
router.post(
'/create_item',
function (
req,
res,
next // Try to create items in database
) {
console.log(req.body);
var itemInfo = req.body;
if (
!itemInfo.itemname ||
!itemInfo.itemdsc ||
!itemInfo.itemstock ||
!itemInfo.itemprice
) {
res.send();
} else {
var NewItem = new Item({
createrId: loggedInUser._id,
productname: itemInfo.itemname,
description: itemInfo.itemdsc,
price: itemInfo.itemprice,
totalStock: itemInfo.itemstock,
});
NewItem.save(function (err, Item) {
if (err) console.log(err);
else console.log('Item added succesfully !');
});
}
User.findById(loggedInUser._id)
.populate('items')
.exec(function (err, result) {
if (err) {
console.log(err);
} else {
console.log('Suceess ? : ', result.items);
console.log(loggedInUser._id);
}
});
}
);
I keep the data for loggedInUser in '/login' so it is return me a value.
My output is
"Suceess ? :[]
6379921faf39150008fa1b88
Item added succesfully !
Which ı think the problem is from the output it trying to populate item after Item is created but how can ı solve this problem ?
Thanks
The problem is that your code is not executing sequentially (NewItem.save logs after User.findById).
Try to use async await, also you will need to add the newly created item _id to the corresponding User to add the new reference to the items array:
router.post(
'/create_item',
async function (
req,
res,
next // Try to create items in database
) {
console.log(req.body);
try {
var itemInfo = req.body;
if (
!itemInfo.itemname ||
!itemInfo.itemdsc ||
!itemInfo.itemstock ||
!itemInfo.itemprice
) {
return res.send('Incomplete parameters');
}
const newItem = await Item.create({
createrId: loggedInUser._id,
productname: itemInfo.itemname,
description: itemInfo.itemdsc,
price: itemInfo.itemprice,
totalStock: itemInfo.itemstock,
});
const result = await User.findByIdAndUpdate(loggedInUser._id, {
$push: { items: newItem._id },
}, { new: true })
.populate('items')
.exec();
console.log('Suceess ? : ', result.items);
console.log(loggedInUser._id);
return res.send('Finished');
} catch (e) {
console.log(e);
}
}
);
In the docs, there is no example to explicitly define ObjectID. I do not want to use autoGenerateObjectIDIfNotExist as it duplicates my objects in the index. Nor do I want to use replaceAllObjects as creates more and more Indices each time.
I am using useEffect to pull the API from MongoDB. How would I define ObjectID by appending a custom ObjectID? Through afor loop?
For reference, this is for a MERN app.
If an ObjectID is not defined this error pops up:
"All objects must have an unique objectID (like a primary key) to be
valid. Algolia is also able to generate objectIDs automatically but
it's not recommended. To do it, use the {'autoGenerateObjectIDIfNotExist': true} option."
useEffect(() => {
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const fetchPasswords = async () => {
const { data } = await axios.get("/api/passwords", config);
setPasswords(data);
};
fetchPasswords();
}, []);
index
.saveObjects(passwords, {
objectIDs: passwords._id,
})
.then(({ objectIDs }) => {
console.log(objectIDs);
});
Once you get back the data. you can run a forEach through the array and replace the _id field with objectID field. After that setPasswords(data)
For an example like this
const data = [
{
_id: 1,
password: 'password1'
},{
_id: 2,
password: 'password2'
},{
_id: 3,
password: 'password3'
}
]
data.forEach((password) => {
password.objectID = password._id;
delete password._id;
})
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const { data } = await axios.get("/api/passwords", config);
//run the forEach for data.....
setPasswords(data);
Now that each record has an objectID you can index your data the usual way like
index.saveObjects(passwords).then(({ objectIDs }) => {
console.log(objectIDs);
});
You can do this like or you can set the objectID from the backend itself and send to frontend.
In my NodeJS and MongoDB app, I have 2 mongoose schemas:
companySchema:
const companySchema = new Schema({
name: {
type: String,
required: true
},
products: [{
type: Schema.Types.ObjectId,
ref: 'Product',
required: false
}]
});
companySchema.statics.addProduct = function (productId) {
let updatedProducts = [...this.products];
updatedProducts.push(productId);
this.products = updatedProducts;
return this.save();
}
module.exports = mongoose.model(‘Company’, companySchema);
productSchema:
const productSchema = new Schema({
name: {
type: String,
required: true
},
quantity: {
type: Number,
required: true
}
});
module.exports = mongoose.model('Product', productSchema);
Every time I add a new product to productSchema, I would like to add the _id of the newly created product to products array in companySchema in order to easily access products later on.
To accomplish this, I wrote:
const Company = require('../models/company');
const Product = require('../models/product ');
exports.postAddProduct = (req, res, next) => {
const name = req.body.name;
const quantity = req.body.quantity;
const product = new Product({
name: name,
quantity: quantity
});
product.save()
.then(product => {
return Company.addProduct(product._id);
})
.then(result => {
res.redirect('/');
})
.catch(err => console.log(err));
}
I am getting an error: TypeError: this.products is not iterable.
You are setting a static method, which is a method on the model rather than the document instance.
Therefore, this refers to the model itself, not the individual document.
Unlike the document, the model doesn’t have an array (iterable) called products so it can’t be spread into a new array.
Try using methods instead of statics:
companySchema.methods.addProduct = function (productId) {
...
}
I hope this helps.
In the below code, I'm creating a checkin document which I then reference in the user document, on top with a car reference (in the user's collection). What I'm trying to achieve is to skip the insert to the array if the car already exists.
How to check it? Or should I work with the model, and define a uniqueness reference in the cars[] array?
router.post('/', (req, res, err) => {
var checkin = new Checkin(req.body);
checkin._id = mongoose.Types.ObjectId();
checkin.save()
.then((checkinDoc) => {
return User.findOneAndUpdate(
{ _id: ObjectID(checkin.user) },
{ $push: { checkins: checkinDoc._id, cars: checkin.car } },
{ new: true }
)
})
.catch((err) => {
res.send(err);
});
});
My user.js model
[...]
cars: [{
type: Schema.Types.ObjectId,
ref: 'Car'
}],
[...]