Reputation: 5039
I have this object:
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877a8"),
"websites" : [
"",
"",
""
],
"keys" : [
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877af"),
"name" : "Google",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ae"),
"name" : "Built With",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ad"),
"name" : "Check Host",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ac"),
"name" : "Alexa",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ab"),
"name" : "Facebook",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877aa"),
"name" : "Instagram",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877a9"),
"name" : "Moz",
"value" : ""
}
],
"username" : "admin@admin",
"isPremium" : false,
"accType" : "admin",
"hash" : "very long hash",
"salt" : "long salt",
}
Now. Using NodeExpress and Mongoose I need to be able to edit the value
field inside of every object inside the keys
array.
My GET
operation is this:
// GET: /websites/:_id - show edit form
router.get('/keys/edit/:_id', isAdmin, function(req, res, next) {
// console.log('tada');
// console.log(req.params._id);
Account.findOne({ _id: req.user._id }, function(err, user) {
var selectedKey = findById(user.keys, req.params._id);
// var keys = user.keys.findOne(req.params._id);
console.log(selectedKey);
res.render('admin/edit', {
title: 'Edit websites',
user: req.user,
value: selectedKey.value,
});
});
});
How the app works is: The admin logs in. He sees all users and chooses which one he wants to modify, then admin sees all keys. I will attach screenshots to explain it more clearly.
Now. I think I know what I need to do, but I have no clue how to translate it to code.
I think I need to: Find the index of the array element, like in the GET request, update the value with the posted value. I think I need to find the index in the array.
But as I said I have no clue how to do it.
My POST looks like this right now:
// POST: /keys/edit/_id - save updates
router.post('/keys/edit/:_id', isAdmin, function(req, res, next) {
var p = req.params;
var b = req.body;
Account.findOne({ _id: req.user._id }, function(err, user) {
var selectedKey = findById(user.keys, req.params._id);
// console.log('Key value: ' + req.body.keyValue);
// console.log('Selected key: ' + selectedKey);
console.log('id:' + req.params._id);
if (err) {
console.log(err);
} else {
console.log(user);
user.keys.set(req.params._id, req.body.keyValue);
user.save(err => {
if (err) {
console.log(err);
} else {
console.log('all good');
}
res.redirect('/admin');
});
}
});
EDIT: So I was working on it for a while now and I figured out this. I am using the correct user, I am grabbing the keys array inside, but I don't know how to find the id of the object in the array, which (object) I need to edit.
There is a lot of nesting and this might cause some issues.
EDIT 2: I'm attacking my account model. Forgot about it earlier. Sorry.
var mongoose = require('mongoose');
var website = require('./website');
var plm = require('passport-local-mongoose');
var accountSchema = new mongoose.Schema({
isPremium: Boolean,
accType: String,
websites: [],
keys: [
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
],
});
accountSchema.plugin(plm);
module.exports = mongoose.model('Account', accountSchema);
Upvotes: 0
Views: 82
Reputation: 75934
You can perform the update atomically using $positional
operator.
You include the field (_id
) from the keys
to locate the index of element and replace the placeholder($
) with the found index from query part in the update part to set the value
in keys
.
router.post('/keys/edit/:_id', isAdmin, function(req, res, next) {
var p = req.params;
var b = req.body;
Account.findOneAndUpdate(
{_id: req.user._id,'keys._id':req.params._id },
{$set:{'keys.$.value':req.body.keyValue}},
{new: true},
function(err, account) {}
);
Upvotes: 1
Reputation: 22952
The question isn't entirely clear to me what you're looking to do, but what I can infer is that you want to do the following:
You have some object that has an Array
of keys
that has the following shape:
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877af"),
"name" : "Google",
"value" : ""
}
Judging from your sample object, I'm inferring the schema is defined something like:
const mongoose = require('mongoose')
const definition = {
websites: [String],
keys: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Key'
}]
}
const accountSchema = new mongoose.Schema(definition)
module.exports = mongoose.model('Account', topicSchema)
By the looks of the route, you want to update/edit that object at the given index: keys[i]
. If this is the case, then there is no need to manually traverse the array, update the model directly:
const Key = require('./path/to/models/Key')
router.post('/keys/edit/:id', async (req, res) => {
const { keyValue } = req.body
const conditions = { _id: req.params.id }
await Key.findOneAndUpdate({ id }, { value: keyValue }).exec()
res.status(201).json()
})
The item in the array will be updated when you query the parent model.
Upvotes: 0