I'm a bit new with mongo node and express and I'm experiencing some problems. I'm trying to query all products in a db based on certain keywords. Ideally, I want to find one product containing words from a user search and defaulting to a fixed product if none of the words are found to be contained in a collection
Here's my schema setup:
var express = require("express"),
mongoose = require("mongoose");
var productSchema = new mongoose.Schema({
name: String,
image: String,
description: String,
keywords: String,
});
module.exports = mongoose.model('Product', productSchema);
My idea is to match users with a product based on their query. Even if they type a full sentence (currently it only works with single words). If there's no product, I want to default to one product in the db. Here's my route setup:
var express = require("express"),
Product =require('../models/product'),
router = express.Router();
router.get('/myroute', function(req,res){
// if there's a query
if(req.query.search){
const regex = new RegExp(escapeRegex(req.query.search), 'gi');
var regexSearch = {
"keywords": {
"$regex": regex
}
};
Product.findOne(regexSearch, function(err, foundProduct){
if(err){
console.log('product not found');
} else{
res.render('show', {product: foundProduct});
}
});
} else{
Product.findOne({name: 'defaultP'}, function(err, foundProduct){
if(err){
console.log(err);
} else{
res.render('show', {product: foundProduct});
}
});
}
});
function escapeRegex(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
module.exports = router;
Currently everything works fine when I search a keyword that exists (But not a sentence). However, if I search for a sentence or a keyword that's not present in the db, I get an error when rendering:
Cannot read property 'name' of null at eval (eval at (/home/ubuntu/workspace/node_modules/ejs/lib/ejs.js:524:12), :22:33) at returnedFn (/home/ubuntu/workspace/node_modules/ejs/lib/ejs.js:555:17) at tryHandleCache (/home/ubuntu/workspace/node_modules/ejs/lib/ejs.js:203:34) at View.exports.renderFile [as engine] (/home/ubuntu/workspace/node_modules/ejs/lib/ejs.js:412:10) at View.render (/home/ubuntu/workspace/node_modules/express/lib/view.js:128:8) at tryRender (/home/ubuntu/workspace/node_modules/express/lib/application.js:640:10) at EventEmitter.render (/home/ubuntu/workspace/node_modules/express/lib/application.js:592:3) at ServerResponse.render (/home/ubuntu/workspace/node_modules/express/lib/response.js:971:7) at /home/ubuntu/workspace/routes/match.js:20:23 at Query. (/home/ubuntu/workspace/node_modules/mongoose/lib/model.js:3755:16) at /home/ubuntu/workspace/node_modules/mongoose/node_modules/kareem/index.js:277:21 at /home/ubuntu/workspace/node_modules/mongoose/node_modules/kareem/index.js:131:16 at nextTickCallbackWith0Args (node.js:436:9) at process._tickCallback (node.js:365:13)
.findOne()actually returned something. When it does not then it isnulland you don't check but just blindly send it to the template. I suspect the reason for no result is the "mangling" of the string being done with the.replace(). Not sure what you are intending to do there, but the output to me would seem unlikely to match any "sentence" stored in the database. - Neil Lunnif (foundProduct != null)and yourelsereturns a "not found" response. Like I said though the.replace()here makes no sense since it's just appending `\` to the end of each word, and I doubt your data is stored like that. - Neil Lunn