Creating a search option in Nodejs with database mongodb - node.js

I'm trying to make a search option by name in node.js and it will search local database, if it finds the name it will display in webpage. But I'm getting the error in this syntax : user.find({id : findname}, which I have used in below code.
router.get('/', function(req, res, next) {
var findname = req.body.findname;
res.render('detail', { title: 'Detail' });
});
mongoose.connect('mongodb://localhost/student');
var testSchema = new mongoose.Schema({
id : Number,
name : String,
email : String,
age : Number,
college : String
});
var user = mongoose.model('stud', testSchema, 'stud');
router.post('/show', function(req, res){
user.find({name : findname}, function(err, docs){
res.render('detail',{users:docs});
});
});

So, the problem is you've defined your findname variable in one function and are trying to use it in another. In order to accomplish what you're looking for, your router.post function should probably look something like this:
router.post('/show', function(req, res){
var findname = req.body.findname
user.find({name : findname}, function(err, docs){
res.render('detail',{users:docs});
});
});
Make sure you're using the correct middleware to populate the req.body object as well, or the code still won't work.

I suggest you to read the mongoose documentation Mongoose Doc. The id (and _id) fields are automatically assigned by Mongoose. The id is a virtual getter on the _id, it is a string or hex representation of the _id. Try to change the name of your field ­id by myId.
Anyway, your id is of type number and your try to match it with findname which is I guess a string ? Is there a type mismatch here ?

Related

Cast error while executing a mongoose query

I am executing a query in mongoose where I need to find all the users in my database and sort them and limit the results to 10.
My query route is:(the route is "/user/top")
router.get('/top', middleware.ensureAuthenticated, function (req, res) {
User.find({}).sort({bestScore: 1}).limit(10).exec(function (err, result) {
if(err){
res.json({
status:"error",
data:err
});
}
else {
res.json({
status:"ok",
data: result
})
}
})
});
My User model:
var UserSchema = new mongoose.Schema({
image: String,
displayName: String,
bestScore:Number,
});
The error while i call the url from postman
EDIT 1:
Output of mongodb query:
You can see that my _id is of type ObjectId .
Your data probably contains a document which looks like this:
{
_id: "top",
...
}
Since Mongoose expects that value to be an ObjectId by default you get this error. What you can do is map the _id field explicitly as a string:
var UserSchema = new mongoose.Schema({
_id: String,
image: String,
displayName: String,
bestScore:Number,
});
The issue you had is that your search route is going through findbyId. if you truly wanna search/find all users without using an Id, you need to make sure in your controller, your search comes before your getbyId. same also in your route. I had the same error here and I was able to solve it from my route by putting my search function before getbyId.
Also, when you are using postman, kindly enter the search parameter as seen in my own case study below;
take note the path and my parameter key and value:

Url parameter in express and mongoose

Im building a basic web app with node/express and mongoose. How do i replace :id in express parameter to a string
For example
mongoose model
var UserSchema = new Schema({
name: String,
});
var User = mongoose.model('User', UserSchema);
Let say there is a user name "Mr robot king" in the User's collection right now
app.get('/:id', function(req, res, next) {
User.findOne({ _id: req.params.id }, function(err, user) {
res.render('home');
});
});
result of the url
localhost:8080/5asdasd43241asdasdasd
What i want is
localhost:8080/Mr-robot-king
In essence, that wouldn't be too difficult:
app.get('/:name', function(req, res, next) {
var name = req.params.name.replace(/-/g, ' ');
User.findOne({ name : name }, function(err, user) {
res.json(user);
});
});
Some considerations:
Since your example replaces spaces with hyphens, and the code above does the opposite, user names with actual hyphens in them will break this substitution scheme;
If user names are allowed to contain characters that have special meaning in URL's (like & or ?), when building the links, you should encode them. So the user name jill&bob will yield the link localhost:8080/jill%26bob
You probably want to add an index to the name field to make sure that queries are fast;
EDIT: to generate these links, for instance from an EJS template, you can use something like this:
go to page

Mongo / Express Query Nested _id from query string

Using: node/express/mongodb/mongoose
With the setup listed above, I have created my schema and model and can query as needed. What I'm wondering how to do though is, pass the express request.query object to Model.find() in mongoose to match and query the _id of a nested document. In this instance, the query may look something like:
http://domain.com/api/object._id=57902aeec07ffa2290f179fe
Where object is a nested object that exists elsewhere in the database. I can easily query other fields. _id is the only one giving an issue. It returns an empty array of matches.
Can this be done?
This is an example and not the ACTUAL schema but this gets the point across..
let Category = mongoose.Schema({
name: String
})
let Product = mongoose.Schema({
name: String,
description:String,
category:Category
})
// sample category..
{
_id:ObjectId("1234567890"),
name: 'Sample Category'
}
// sample product
{
_id:ObjectId("0987654321"),
name:'Sample Product',
description:'Sample Product Description',
category: {
_id:ObjectId("1234567890"),
name: 'Sample Category'
}
}
So, what I'm looking for is... if I have the following in express..
app.get('/products',function(req,res,next){
let query = req.query
ProductModel.find(query).exec(function(err,docs){
res.json(docs)
})
})
This would allow me to specify anything I want in the query parameters as a query. So I could..
http://domain.com/api/products?name=String
http://domain.com/api/products?description=String
http://domain.com/api/products?category.name=String
I can query by category.name like this, but I can't do:
http://domain.com/api/products?category._id=1234567890
This returns an empty array
Change your query to http://domain.com/api/object/57902aeec07ffa2290f179fe and try
app.get('/api/object/:_id', function(req, res) {
// req._id is Mongo Document Id
// change MyModel to your model name
MyModel.findOne( {'_id' : req._id }, function(err, doc){
// do smth with this document
console.log(doc);
});
});
or try this one
http://domain.com/api/object?id=57902aeec07ffa2290f179fe
app.get('/api/object', function(req, res) {
var id = req.param('id');
MyModel.findOne( {'_id' : id }, function(err, doc){
console.log(doc);
});
})
First of all increase your skills in getting URL and POST Parameters by this article.
Read official Express 4.x API Documentation
Never mind I feel ridiculous. It works just as I posted above.. after I fixed an error in my schema.

Cannot read from database using mongoose

This is my GET request
var Catalog = mongoose.model('Catalog');
router.get('/catalog', function(req, res, next) {
Catalog.find(function(err, items){
if(err){
return next(err);
}
console.log(items);
res.json(items);
});
});
The model
var mongoose = require('mongoose');
var CatalogSchema = new mongoose.Schema({
title: String,
cost: String,
description: String
});
mongoose.model('Catalog', CatalogSchema);
The console.log gives me a [] but there is a collection named Catalog with the parameters filled.
If you have an existing collection, created outside of Mongoose, that you wish to query you need to configure your model to use that collection.
Otherwise, Mongoose will use a utility function to create a collection name by pluralizing and lowercasing the model name (which in your case would become catalogs).
To use Catalog as a collection, use the collection option:
var CatalogSchema = new mongoose.Schema({
title: String,
cost: String,
description: String
}, { collection : 'Catalog' });
you might check again the collection name in mongodb i.e whether it is 'Catalog' or 'Catalogs'. In my experience I found that if you name the model 'Catalog', then either mongoose creates the collection with a name 'Catalogs' if it is not already there or you have to create the collection first with a name 'Catalogs'.
You might check the following line also:
Catalog.find({}, function(err, items){
// your code goes here
}
Hope it helps..

nodeJS + MongoDB + Mongoose - Unable To Delete 1 Entry

I'm using nodeJS MongoDB/Mongoose to create/update/delete movies inside the database using Postman post/delete methods.
The create function is working fine, and even the remove function is working properly so when I use Postman I get the return: "Movie has been deleted!" like it should.
The only problem is that my function is emptying the entire database of movies instead of just that 1 movie, here is the remove function:
function destroy(req, res, next){
var movieID = req.body
Movie.remove(movieID, function(err,movie){
if(err){
res.status(400).send(err)
} else {
res.send("Movie has been deleted!")
db.close()
}
})
The movie object:
var movieSchema = new mongoose.Schema({
name: String,
yay: Number,
nay: Number,
release_date: Date,
in_theaters: Boolean,
released: Boolean,
buy_link: String,
imdb_link: String,
image_url: String,
description: String,
trailer_link: String
})
I want to delete a movie based on it's "name" so I only have to input the name and it will delete the entire movie.
Have you tried the findOneAndRemove query?
This query is much cleaner compared to finding a model and removing it inside the callback. Beside this I assume it's faster because you basically do 1 query instead of 2 after each other.
If you are passing direct value to Remove method, it will try to match with _id field.
As per your model, _id is ObjectId field which is managed automatically by mongodb.
In case if you enter like this. .remove("movie", callback) which is not a valid ObjectId.
Mongoose is discarding this invalid condition and executing Movie.remove({}); which is deleting all your records.
So it is better to validate whether the input is valid ObjectId or not before directly passing to Movie.remove();
I also recommend to use like this: Movie.remove({_id: movieId}, callback).
And for movie name :
Movie.remove({name: movieName}, callback);
Update:
You can take from Postman
var movieName = req.body.movieName;
Movie.remove({name: movieName}, function(err, updateObj){
});
Can you try this?
var movieName = req.body.name;
Movie.find('name': movieName, function(err, movie) {
if (err) res.send({error: err});
Movie.remove(function(err, movie){
if (err) res.send({error: err});
res.json({message: "Movie is removed", movie: movie});
});
});

Resources