0

I am currently running MongoDB locally version 3.2.3. Current Node Server version 7.2.0. The API was written in Typescript.

List of relevant dependencies:

"dependencies": {
    "@types/mongoose": "^4.7.3",
    "@types/node": "^6.0.56",
    "bcrypt-nodejs": "0.0.3",
    "body-parser": "^1.15.2",
    "compression": "^1.6.2",
    "dotenv": "^4.0.0",
    "ejs": "^2.5.5",
    "express": "^4.14.0",
    "mongodb": "^2.2.21",
    "mongoose": "^4.7.6",
    "path": "^0.12.7"
  }

My server.js file relevant statements:

// Modules extending node
import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as http from 'http';
import * as path from 'path';

// Custom modules imported.  Some are routers behaving as miniapps routed to the main app.
import { digitalAssetRouter } from './api/digitalMedia/digitalmediaController';

/**
 * Node Express Server Controller
 */

let app = express();

app.use((req, res, next)=>{
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3050');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views/'));
let server = http.createServer(app);

//Configure express
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use((err, req, res, next) =>
    res.status(500).send(JSON.stringify({ err: 'Bad API Request!' }))
);

//Route
app.use('/', indexRouter);
//API Routes

// API Information
app.use('/api/v1', digitalAssetRouter);

// Digital Assets
//GET ALL AND POST CREATE ONE
    app.use('/api/v1/digitalassets', digitalAssetRouter); 
//GET ONE BY ID, PUT ONE BY ID, DELETE ONE BY ID
    app.use('/api/v1/digitalassets/:digitalassetsId', digitalAssetRouter);
//UPDATE BY ID I TRIED BOTH WAYS, ABOVE AND BELOW
    app.use('/api/v1/digitalassets/update/:digitalassetsId',      digitalAssetRouter);

// catch 404 and forward to error handler
app.use((req, res, next) => {
    let err = new Error('Not Found');
    err.message = '404';
    next(err);
});

// error handler
app.use((err, req, res, next) => {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};

    // render the error page
    res.status(err.status || 500);
    res.render('error');
});


//server start
server.listen(3000, () => {
    console.log('LOCALHOST Running @ port 3000');
    console.log(app.get('env'));
});

//Expose server module
export { app };

Below is my controller relevant methods:

/**
 * Digital Media Controller Module
 */

import * as express from 'express';
import { digitalAsset } from './digitalmediaModel';

//Creates a mini app that only handles routes for digital assets
let digitalAssetRouter = express.Router();

/**
 * UPDATE ONE BY ID
 * Patch attributes for a model instance and persist it into the data source.
 */
digitalAssetRouter.put('/digitalassets/:digitalassetsId', (req, res, next) => {
    console.log(req.params);
    console.log(req.body);
    digitalAsset.findByIdAndUpdate(req.params.digitalassetsId, req.body)
        .then(response => {
            res.status(200).json({
                comment: 'Patch attributes for a model instance and persist it into the data source.',
                responseType: 'success'
            });
        })
        .catch(err => {
            // console.log(err);
            res.status(400).json({
                error: "Cannot find digital image with id: " + req.params.digitalassetsId,
                errorMessage: err
            });
        });
});

I read the documentation directly from mongoose regarding findByIdAndUpdate. I have made several attempts to modify the way I send data to update via postman.

Postman PUT method to api endpoint to update by id I also put Content-Type is application/json in headers. The payload being sent was raw data in JSON format shown below. This is what appears in console.log(req.body):

{
    "altText" : "Canon alt text"
}

Below is my model of a digitalasset:

/**
 * Digital Media Model
 */
import { mongooseDb } from '../../config/db';
mongooseDb.Promise = global.Promise;

let Schema = mongooseDb.Schema;
let TagsSchema = new Schema({
    id: String,
    name: String,
    app_id: String,
    value: Number
},
    { _id: false });

let ExifSchema = new Schema({
    make: String,
    model: String,
    width: Number,
    length: Number,
    created: String,
    fileSource: String,
    exposureMode: String,
    exposureTime: String,
    aperture: Number,
    iso: Number,
    exposureBias: Number,
    flash: String,
    orientation: String
},
    { _id: false });

let DigitalAssetSchema = new Schema({
    fileName: String,
    title: String,
    caption: String,
    altText: String,
    description: String,
    fileType: String,
    uploadedOn: {
        type: Date,
        default: Date.now,
    },
    uploadedBy: String,
    fileSize: {
        type: Number,
    },
    url: {
        type: String
    },
    relativePath: String,
    categories: [String],
    tags: [TagsSchema],
    exif: ExifSchema,
    embedUrl: String,
    shareUrl: String
});

let digitalAsset = mongooseDb.model('digitalAsset', DigitalAssetSchema);

export { digitalAsset };

I have no problem creating documents in the database and deleting them. When it comes to updating them via PUT method using express routing, the process is not working. I have tried different variations just to change one field in the document chosen with no success. I provide examples below of screenshots in Postman:

I have some records in MongoDB to update as follows.

{
    "_id" : "589739a960aa6d23823cafb9",
    "altText" : "CHANGE",
    "description" : "CHANGE",
    "relativePath" : "assets/Pics/high resolution/purchasable pictures/various.corbis/Internet/42-17083495.jpg",
    "fileName" : "/disk/assets/Pics/high resolution/purchasable pictures/various.corbis/Internet/42-17083495",
    "fileSize" : 8220,
    "title" : "CHANGE",
    "fileType" : ".jpg",
    "caption" : "CHANGE",
    "uploadedBy" : "rmore071",
    "__v" : 0,
    "tags" : [ 
        {
            "name" : "people",
            "value" : 0.98049
        }, 
        {
            "name" : "outdoors",
            "value" : 0.9785451
        }, 
        {
            "name" : "architecture",
            "value" : 0.95540833
        }, 
        {
            "name" : "horizontal plane",
            "value" : 0.955212
        }, 
        {
            "name" : "travel",
            "value" : 0.95194626
        }, 
        {
            "name" : "industry",
            "value" : 0.9321301
        }, 
        {
            "name" : "flame",
            "value" : 0.9265379
        }, 
        {
            "name" : "man",
            "value" : 0.9220996
        }, 
        {
            "name" : "business",
            "value" : 0.91815794
        }, 
        {
            "name" : "heat",
            "value" : 0.89368707
        }, 
        {
            "name" : "no person",
            "value" : 0.89319044
        }, 
        {
            "name" : "panoramic",
            "value" : 0.8734973
        }, 
        {
            "name" : "illuminated",
            "value" : 0.8665502
        }, 
        {
            "name" : "adult",
            "value" : 0.86405236
        }, 
        {
            "name" : "fossil fuel",
            "value" : 0.8607676
        }, 
        {
            "name" : "transportation system",
            "value" : 0.8506778
        }, 
        {
            "name" : "competition",
            "value" : 0.83268094
        }, 
        {
            "name" : "building",
            "value" : 0.8307033
        }, 
        {
            "name" : "action",
            "value" : 0.8292489
        }, 
        {
            "name" : "horizontal",
            "value" : 0.829162
        }
    ],
    "categories" : [],
    "uploadedOn" : "2017-02-05T14:41:45.984Z"
}

When I hit send in Postman I get:

{
  "comment": "Patch attributes for a model instance and persist it into the data source.",
  "responseType": "success"
}

This tells me that the promise did not return an error and printed out the contents in the then() function since the id was accepted.

However with a quick look in the database using RoboMongo, I see the field altText has not been updated.

My question is exactly as titled, How do I update with PUT method? I am doing something wrong, and would really like another pair of eyes to glance over and see what I did wrong. Thank you in advanced for your time.

2
  • I've been playing around with similar code for a few hours to try to replicate but I can't. What's the output of console.log(response) inside the then of findByIdAndUpdate? Commented Feb 12, 2017 at 5:33
  • @LuisDiegoHernández To answer your question the response would be null. It turns out that as a value for my _id key is a string. When I turned on mongoose debugging, explained here, I noticed that mongoose was sending: Mongoose: digitalassets.findOne({ _id: ObjectId("58969de160aa6d23823c9e69") }, { fields: undefined }), and the value in the database was string. So the response would be null because the query did not find a value ObjectId("58969de160aa6d23823c9e69"). Commented Feb 12, 2017 at 13:11

1 Answer 1

2

It turns out that as a value for my _id key is a string in the database. When I turned on mongoose debugging, explained here, I noticed that mongoose was sending: Mongoose: digitalassets.findOne({ _id: ObjectId("58969de160aa6d23823c9e69") }, { fields: undefined }), and the value in the database was string. So the response would be null because the query did not find a value ObjectId("58969de160aa6d23823c9e69"). I corrected the issue by updating the values for the _id keys from strings to Objects, i.e. ObjectId("58969de160aa6d23823c9e69").

I suspect when I created a local development database environment and copied a subset of documents from my live database to the development database, ObjectId values were changed to strings, causing the issue of getting null responses from Mongoose's method findByIdAndUpdate(), executed in a PUT express route.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah, I see. I thought it could have something to do with findByIdAndUpdate's automatic application of ObjectId function, but I wasn't sure. It was an interesting issue.

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.