Reputation: 21
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.
Upvotes: 0
Views: 4791
Reputation: 21
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.
Upvotes: 2