1

I'm having a bit of a struggle with updating my mongodb database with new records. The database consists of fields of exercises that are arrays and when I do a PUT header I'd like to update the specific exercise with a new record, not override the whole field of specific exercise as I'd like to keep the history of progress. So far I can only GET the specific nested fields as seen in router.get('/:nickname/:info'), where we can specify the user and their name, age or gender. I can do the same with exercises field, but I keep failing at updating those. Here's the database:

[
{
    "_id": "59283956c52a5420e74966b9",
    "info": {
      "nickname": "annwumy",
      "name": "Bert",
      "gender": "male",
      "age": 25
    },
    "exercises": [
      {
        "exercise": {
          "name": "squats",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "legpresses",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "deadlifts",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "benchpresses",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "pullups",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "shoulderpress",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "curls",
          "records": []
        }
      }
    ]
  },
  {
    "_id": "5928397fc52a5420e74966ba",
    "info": {
      "nickname": "mmsmsy",
      "name": "Mateusz",
      "gender": "male",
      "age": 26
    },
    "exercises": [
      {
        "exercise": {
          "name": "squats",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "legpresses",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "deadlifts",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "benchpresses",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "pullups",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "shoulderpress",
          "records": []
        }
      },
      {
        "exercise": {
          "name": "curls",
          "records": []
        }
      }
    ]
  }
]

And here's the back-end code with requests:

const express = require('express');
const router = express.Router();
const app = express();
const cors = require('cors');
const bodyParser = require('body-parser');
const axios = require('axios');

const monk = require('monk');
const db = require('monk')('localhost/fitness-log');
const users = db.get('users');

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.use('/api/v1', router);


router.get('/listusers', (req, res) => {
  users.find()
    .then(users => res.json(users))
});

router.get('/users/:id', (req, res) => {
  users.find({'_id': req.params.id})
    .then(user => res.json(user[0]))
});

router.get('/:nickname/:info', (req, res) => {
  users.find({'nickname': req.params.nickname}, `info.${req.params.info}`)
    .then(user => res.json(user[0]))
});

router.post('/adduser', (req, res) => {
  users.insert(req.body, (err, result) => {
    res.send(
      (err === null) ? { msg: result } : { msg: err }
    );
  });
});

router.put('/updateinfo/:nickname/:info', (req, res) => {
  const updateQuery = {$set: {}};
  updateQuery.$set[`info.${req.params.info}`] = req.body.value;
  users.update({'nickname': req.params.nickname}, updateQuery, (err, result) => { 
    res.send(
      (err === null) ? { msg: result } : { msg: err }
    );
  });
});

router.put('/addrecord/:nickname/:exercise', (req, res) => {
  const updateQuery = {$push: {}};
  updateQuery.$push[`exercises.${req.params.exercise}`] = req.body;
  users.update({'nickname': req.params.nickname}, updateQuery, (err, result) => { 
    res.send(
      (err === null) ? { msg: result } : { msg: err }
    );
  });
});

router.delete('/deleteuser/:nickname', (req, res) => {
  users.remove({ 'nickname': req.params.nickname }, err => {
    res.send((err === null) ? { msg: '' } : { msg: 'error: ' + err});
  });
});

router.delete('/deleteallusers', (req, res) => {
  users.remove({}, err => {
    res.send(err === null) ? {msg: '' } : { msg: 'error: ' + err};
  });
});

app.listen(3001, () => console.log("Server running at 3001"));

1 Answer 1

1

The bug is in the update expression:

{$set: `info.${req.params.info}`}

It's need to be:

const updateQuery = {$set: {}};
updateQuery.$set[`info.${req.params.info}`] = req.params.infoValue;
users.update({'nickname': req.params.nickname}, updateQuery, (err, result) => { 
Sign up to request clarification or add additional context in comments.

6 Comments

Great tip. thank You. I've updated the code, so that it updates the specific exercise. It still overwrites the exercise record, when I try to PUT new record. I would like it to store the new record next to the previous ones in an array of objects. The one You've suggested will work nicely with updating user name, age and gender info though.
You need to change the document structure. Change exercises to array, and insert new exercise with $push instead of $set - docs.mongodb.com/manual/reference/operator/update/push
You're a magician. :) Thank You very much, everything worked as soon as I changed $set to $push in the update query.
Nice to help you :)
I've recreated the database schema, so that it's easier to access and map the exercises in front-end, however now I'm struggling again with updating the right field. Would You have any idea how to edit the $push method to update the right exercises.exercise.[specified_name] record that's the field next to "name" field?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.