Finding a MongoDB document by ObjectId with Mongoose - node.js

I am trying to update a document in MongoDB by finding it by the ObjectId. The work flow is as follows (this is for a blog).
Create a new post in MongoDB by passing a title and body. The ObjectId is automatically created.
Go to edit the post. It uses the ObjectId from the URL to grab it from the database and display it in the same new post form, just with the preexisting values.
When the submit button is clicked I want to find the document by the ObjectId and update the values in the database with those in the post form.
Step 1 & 2 work fine, but step 3 doesn't seem to be working. It redirects to the page I need it to. But the database has not been updated. It's the same value as it was before.
Here's the relevant code for the update post portion:
app.js
app.post "/office/post/:id/update", ensureAuthenticated, routes.updatePost
routes/index.js
mongoose = require 'mongoose'
ObjectId = mongoose.Types.ObjectId
Post = require '../models/Post'
...
updatePost: function(req, res) {
var o_id, the_id;
the_id = req.params.id;
console.log(the_id); // 510e05114e2fd6ce61000001
o_id = ObjectId.fromString(the_id);
console.log(o_id); // 510e05114e2fd6ce61000001
return Post.update({
"_id": ObjectId.fromString(the_id)
}, {
"title": "CHANGE"
}, res.redirect("/office/edit/posts"));
}
I'm using Express and Mongoose.
This is also the post model if that helps:
(function() {
var Post, Schema, mongoose;
mongoose = require('mongoose');
Schema = mongoose.Schema;
Post = new Schema({
title: String,
subhead: String,
body: String,
publish_date: {
type: Date,
"default": Date.now
},
mod_date: {
type: Date,
"default": Date.now
}
});
module.exports = mongoose.model('Post', Post);
}).call(this);
And here's the code for the edit blog post view:
app.js
app.get("/office/post/:id/edit", ensureAuthenticated, routes.editPost);
routes/index.js
editPost: function(req, res) {
return Post.findById(req.params.id, function(err, post) {
return res.render('edit-post', {
post: post,
title: post.title
});
});
}

The problem is how you call update
return Post.update({
"_id": ObjectId.fromString(the_id)
}, {
"title": "CHANGE"
}, res.redirect("/office/edit/posts"));
The last argument will actually redirect the page, whereas update expects a function to be called when the update is complete
You should pass in
return Post.update({
"_id": ObjectId.fromString(the_id)
}, {
"title": "CHANGE"
}, function(err, model) {
if (err) // handleerr
res.redirect("/office/edit/posts"));
});
That way, we only redirect once the model is successfully updated

Related

Subdocument does not update - mongoose

I'm trying to update a subdocument of the parent document.
I have a document called "Post" and I reference the "User" document like this:
const PostSchema = new mongoose.Schema({
title: String,
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
},
{ collection: 'posts' })
const Post = mongoose.model('Post', PostSchema);
module.exports = Post;
I'm trying to change the name, for example of whoever posted it. The name field is in "User".
I'm trying to change it this way:
exports.update = async (req, res) => {
//find user by its id, update its post with what's in req.body
Post.findById(req.body.id, function(err, result) {
console.log(result)
if (!err) {
if (!result){
res.status(404).send('User was not found');
}
else{
result.user.nome = "User Name";
result.markModified("user");
result.save(function(saveerr, saveresult) {
if (!saveerr) {
res.status(200).send(saveresult);
} else {
res.status(400).send(saveerr.message);
}
});
}
} else {
res.status(400).send(err.message);
}
}).populate("user");
}
This is my route.js
app.put(
"/api/produtor/update",
controller.update
);
When I run it on the postman, I get status 200 and the name appears modified in the return, but it is not saved in the bank.
I would appreciate it if someone could help me analyze it!
This might be outdated but as per this GitHub comment, this might not be possible out of the box.
I would suggest to update the User by using User schema instead of going through the Post Schema.

Problem with a Cast using Router.put with mongoDB in MERN app

I want to attach the router.put which will update the Boolean(isOn) in toggle button but firstly I wanted to try how it works and now I am facing the problem.
const express = require("express");
const router = express.Router();
const Buttons = require('../../models/Buttons');
// GET buttons
// This request works perfect
router.get('/', (req,res) => {
Buttons.find()
.sort({name: 1})
.then(buttons => res.json(buttons))
});
// PUT buttons
// This one doesnt work at all
router.put('/:name', function(req,res,next) {
Buttons.findByIdAndUpdate({name: req.params.name},
req.body).then(function(){
Buttons.findOne({name: req.params.name}).then(function(buttons){
res.send(buttons);
});
});
});
module.exports = router;
Model of buttons has only name: String, required: true and isOn: Boolean, required: true and data in db looks like that:
Can you tell me what did I do wrong here?
Code of Buttons modal :
const mongoose = require('mongoose');
const Schema = mongoose.Schema
const buttonSchema = new Schema ({
name: {
type: String,
required: true
},
isOn: {
type: Boolean,
required: true
}
});
module.exports = Buttons = mongoose.model("buttons", buttonSchema);
You ca only use findByIdAndUpdate when you want to update the document by matching the _id of the document
If you want to match the document by any other property (such as name in your case), you can use findOneAndUpdate
Write your query like this
router.put('/:name', function(req,res,next) {
Buttons.findOneAndUpdate({name: req.params.name},
req.body).then(function(){
Buttons.findOne({name: req.params.name}).then(function(buttons){
res.send(buttons);
});
});
});
Hope this helps
Please add your id as well which you have to update in your database
Model.findByIdAndUpdate(id, updateObj, {new: true}, function(err, model) {...
This error occur because findByIdAndUpdate need id of an Object which we want to update so it shows ObjectId error. so pass your id from front end and use it in your back-end to update particulate data.
step 1 : you can create new endpoint for update-name
router.put('/update-name', function(req,res,next) {
//here you can access req.body data comes from front-end
// id = req.body.id and name = req.body.name then use it in your
Buttons.findByIdAndUpdate(id, { name : name }, {new: true}, function(err, model) {...
}
step 2 : try this endpoint /update-name and pass your data in Body from postman

KeystoneJS: keystone.list is not a function

I want to make a mongoose query from KeystoneJS. Something like below:
var keystone = require('keystone'),
Post = keystone.list('Post');
Post.model.find()
.where('state', 'published')
.populate('author')
.sort('-publishedAt')
.limit(5)
.exec(function(err, posts) {
// do something with posts
});
I checked the KeystoneJS v5, list created like:
keystone.createList('Post', {
fields: {
title: { type: Text },
},
});
If I query like:
var Post = keystone.list('Post');
I got keystone.list is not a function,
anyway to make a KeystoneJS retrieve query results?

Handling arrays with express post request

I'm using express to make the API for my web app. Below is the Schema for my annual budgets collection.
var {mongoose} = require('../db/mongoose');
var budgets = new mongoose.Schema({
year: Number,
categories: [{
name: String,
amount: Number
}]
});
var Budgets = mongoose.model('Budgets', budgets);
module.exports = {
Budgets
};
I am trying to passing in an array of categories using postman in the following way:
{
"year":2018,
"categories": [{
"name":"Logistics",
"amount":1500
}, {
"name":"Finance",
"amount":23030
}]
}
This the post request for my this collection. The request times out and is not saved in the database. I cannot seem to figure out what is wrong with the request. Please help
app.post('/annualBudgets', (req, res) => {
var categories = req.body.categories;
var budgets = new Budgets({
year : req.body.year,
});
budgets.categories.push(categories);
budgets.save().then((docs) => {
res.send(docs);
console.log(docs)
}).catch((e) => res.status(404));
});
The problem is here
budgets.categories.push(categories);
it should be
budgets.categories = categories;
// Alternatively
// budgets.categories.push(...categories);
because categories is already an array.

Search in mongoosastic doesn't give any result

I tried to use mongoosastic search but it doesnt work
Job.js (Mongoose schema)
var mongoose = require('mongoose');
var mongoosastic = require('mongoosastic');
var Schema = mongoose.Schema;
var JobSchema = Schema({
title: { type: String, es_indexed:true },
category: { type: Schema.Types.ObjectId, ref: 'Category', es_indexed:true},
salary: { type: String, es_indexed:true },
});
JobSchema.plugin(timestamps);
JobSchema.plugin(mongoosastic, {
hosts: [
'localhost:9200'
]});
module.exports = mongoose.model('Job', JobSchema);
Routes.js
var express = require('express');
var app = express();
var Job = require('../models/job');
Job.createMapping(function(err, mapping) {
if (err) {
console.log('error creating mapping (you can safely ignore this)');
console.log(err);
} else {
console.log('mapping created!');
console.log(mapping);
}
});
app.post('/api/search/', function(req, res, next) {
Job.search({query_string: {query: req.body.test}}, function(err, results) {
if (err) return next(err);
res.send(results);
});
});
This is the data sets that already been saved in mongodb
{
"id": 12313,
"title": "Engineer"
},
{
"id": 13123,
"title": "Doctor"
},
{
"id": 121243134,
"title": "Software Engineer"
}
When I tried to run the search and search like "Engineer" and I keep getting this result.
Updated for Curl
curl -XGET localhost:9200/_mapping
curl -XGET localhost:9200/_search
Since title is an analyzed String, its value is indexed using the standard analyzer, i.e. in lowercased form, so "Engineer" will be indexed and "engineer"
Try searching for "engineer" in lowercase instead.
UPDATE
Based on our discussion, it seems that the problem is simply that your Elasticsearch is empty. Since you have existing data in MongoDB, you need to make sure to call the synchronize() method on your model in order to index all your MongoDB collection inside Elasticsearch.

Resources