amazingcode12
amazingcode12

Reputation: 55

Express.js & Mongoose: access Object attribute name by the request parameter

The Context

The problem is that I would like to access the attribute of an Object by the variable passed in the request made. A GET /modify/:var request is made to modify the attribute of a saved document in MongoDB. To know which attribute of the doc, converted to an Object when fetched, we would like to modify, we need the string passed in the :var.

The Route

 public modify(req: express.Request, res: express.Response, next: express.NextFunction)
  {
    Model.findOne({attr: true}, (err, result) => {
      if (err) {
        console.log(err);
      }
      else {
        let copy = result;
        copy.attr.one.(req.params.var) = false; // here
      }
    });
  }

Update

After the answer of Paul, I edited my code and it is returning a 500 status code. I edited

router.put('/route/:var')

public mock(req: express.Request, res: express.Response, next: express.NextFunction) {
      Model.findOne({attr: false}, (err, doc) => {
        doc.attr[req.params.var] = false;
        model.save((e) => {
        if (e){
        console.log(e);
        }
          res.send(doc);
        });
    });

The Model Structure

export interface Model extends mongoose.Document {
  attr: {
             one:   {value: Boolean},
             two:   {value: Boolean},
             three: {value: Boolean},
             four:  {value: Boolean},
           };

}

Upvotes: 2

Views: 1749

Answers (2)

Paul
Paul

Reputation: 36319

Ok, so first off, you should not be using GET requests to modify anything a GET request is just supposed to be a query, without changing anything on the server.

What you're looking for is a PUT request, which is used to modify an existing resource.

Second, you're trying to modify an object, but you don't actually have an object yet. Your findOne has to have something to query with. If you have a URL like http://example.com/modify/name what do you expect to happen? There's no way to tell which name you're modifying or what you're modifying it to.

Even if you're just doing a Boolean like you suggested, taking a given bool variable and setting it false, your URL won't tell you which model should have this variable set to false.

Instead, you could set it up to make a PUT request to (e.g.) /things/:thingId (where the thingId is a unique identifier for any given Thing you are modeling). This would require your client to send all updateable attributes in the body of the request.

Alternately, you could set up a PUT to /things/:thingId/:attr if you want to allow it to modify just one attribute of the thing selected. In that case, your handler would look something like this:

app.put('/things/:thingId/:attr', (req, res, next) => {
  // note, I normally do this kind of thing in an `app.param()` or `router.param()` call.  Included here for brevity.
  Thing.findById(req.params.thingId, (err, thing) => {
     thing[req.params.attr] = req.body[attr];
     thing.save((e) => {
        // todo: handle the error
        res.send(thing);
     });
  });
});

Callbacks are a bit more nested here than I'd normally do, as I said, but hopefully you get the general idea.

Upvotes: 1

Anupam
Anupam

Reputation: 201

you have query expression error

Model.findOne({attr: {$exists:true}}, (err, result) => {
      if (err) {
        console.log(err);
      }
      else {
        let copy = result;
        copy.attr.(req.params.var) = false; // here
      }
    });

Upvotes: 0

Related Questions