How to Make full dynamic search in mongoDB? - node.js

I want to make full dynamic search, when user used to type one or two string characters of book in book store UI at search box it should bring all match value from my book table that can be entire my table.
The kind of object that user want to search is not important it should bring all matched values.
const searchObjects = req.query;
const result =await modelbook.find({
//this place is for query that i don't know how I should write
});
res.status(200).json({resultis: result});
})
and book model has these properties
name
price
Url
author
...

You should use $regex.
const search = asyncWrapper(async (req, res) => {
var { value } = req.query;
const result = await modelbook.find({
$or: [
{ name: { $regex: value, $options: "i" } },
{ price: { $eq: Number(value) ? +value : 0 } },
{ url: { $regex: value, $options: "i" } },
{ description: { $regex: value, $options: "i" } },
{ author: { $regex: value, $options: "i" } }
],
});
res.status(200).json({ resultis: result });
})

Related

Perform full search (using `$regex`) on several fields if search term is presented using aggregation

I have a service that displays products. I need to be able to search products by their fields (product name, barcode or sku).
Previously I used this approach
const query: FilterQuery<TProductSchema> = {};
if (search) {
query.$or = [
{
productName: {
$regex: String(search).split(' ').join('|'),
$options: 'i',
},
},
{
barcode: {
$regex: String(search),
$options: 'i',
},
},
{ sku: { $regex: String(search).split(' ').join('|'), $options: 'i' } },
];
}
if (folderId && folderId !== 'all') {
query.folder = { _id: folderId };
}
const products = await ProductModel.find<HydratedDocument<TProductSchema>>(query)
.limit(Number(limit) === -1 ? 0 : Number(limit))
.skip(Number(page) * Number(limit));
and it worked well but now I also need to include all documents count (which changes depending on selected folderId) in the resulting object.
I thought I could do it with the aggregation framework but I can't figure out how to conditionally match documents only if search is presented.
I thought I could do something like that
const products = await ProductModel.aggregate([
{ $match: {/* match folder */ },
{ /* count matched documents */ },
// next search documents IF `search` is present
{
$match: {
$cond: [search, /* here goes `query` object, '']
}
},
]);
but it doesn't work saying unknown top level operator "$cond"
So how can I apply $match conditionally?
You have created query in first code and you need to pass same in $match it should work same.
$match: query

$or Operator in Mongoose

I am using the $or operator in mongoose for searching through the name and description fields of the database. I want to check if the queryWord string contains any part of the database field(s). This is the code I am using:
const query = {
$or: [
{ name: `/${body.queryWord}/i` },
{ description: { $regex: `/${body.queryWord}/i` } },
],
};
Food.find(query, (err, data) => {
if (err) {
res.status(500).send(err);
} else {
res.status(200).send(data);
}
});
But it returns, only, an empty array!
Any help is greatly appreciated!
Thank You!
I think the problem is because you wrap the regular expression in ``, which is understood as a string. You can try this way:
const queryWordRegex = new RegExp(body.queryWord, "i");
const query = {
$or: [
{ name: { $regex: queryWordRegex } },
{ description: { $regex: queryWordRegex } },
],
};

How to look for strings in array using regex with MongoDB.?

I have several objects like this:
"status": "published",
"term_id": [
"anime",
"sci-fi",
"etc"
],
"captionCert": "1",
I know that in order to look within a single field, I would create something like this:
if (keyword) {
query.status = { $regex: keyword, $options: 'i' };
}
Where keyword comes from the front end and can be whatever the user types; then I proceed to look into the field status and then I just retrieve it by passing it into my model query:
Video.find(query)
Now hte problem is that I need to know how to exactly do this but inside the term_id array?
Any idea? Thanks.
UPDATE: I'm trying to implement it into this function:
exports.searchVideos = asyncHandler(async (req, res, next) => {
const query = {};
const { keyword } = req.query;
if (keyword) {
query.title = { $regex: keyword, $options: 'i' };
} else {
query.text = { $regex: keyword, $options: 'i' };
}
if (keyword) {
query.term_id = { term_id: { $regex: keyword, $options: 'i' } };
};
const video = await Video.find(query).select(
'title text thumbnail video_url term_id'
);
console.log(query);
res.status(200).json({ success: true, data: video });
});
Solution after finding out about $or operator. This solved my problems!:
exports.searchVideos = asyncHandler(async (req, res, next) => {
let query = {};
const { keyword } = req.query;
query = {
$or: [
{ title: { $regex: keyword, $options: 'i' } },
{ text: { $regex: keyword, $options: 'i' } },
{ term_id: { $regex: keyword, $options: 'i' }}
]
};
const video = await Video.find(query).select(
'title text thumbnail video_url term_id'
);
res.status(200).json({ success: true, data: video });
});

NodeJS Mongoose wont accept string variable in $regex

I got one record with admin.name = "FooBar"
And I want to do a findOne on the name but case insensitive.
In Studio3T this works fine...
db.admin.findOne(
{ name: { $regex: /^FoObAr/i } }
)
But in nodeJS I cant seem to get a variable containing the regexp into the find statement...
Let ID = "FoObAr"
return resolve( adminModel.findOne( { "name" : { $regex: "/^" + ID + "$/i"} } ) );
This one results in... (which gives 0 results)
Mongoose: admin.findOne({ name: { '$regex': '/^FoObAr$/i' } }, { projection: {} })
I also tried
Let ID = "FoObAr"
return resolve( adminModel.findOne( { "name" : { $regex: /^ ID $/i } ) );
This one results in... (which gives 0 results)
Mongoose: admin.findOne({ name: { { $regex: /^ ID $/i } }, { projection: {} })
Any ideas?
Please use RegExp function
admin.find({name:new RegExp(['^',ID, '$'].join(''), 'i')}).projection({})
You should pass RegExp object, not string.
adminModel.findOne({ "name" : { $regex: new RegExp(/^FoObAr/, 'i') } })
With variable ID it will look like
adminModel.findOne({ "name" : { $regex: new RegExp(`^${ID}$`, 'i') } })

When i pass null value in search parameter it display no record mongoDB

I am passing blank('') value in search parameter, it display no record. I want, when i pass null or blank value it ignore that parameter from search query, and display record. My code is
var _branchName = req.query.branchName;
var _personName = req.query.personName;
var _clientID = req.query.clientID;
var _searchQRY = [
{
branchName: { $regex: _branchName, $options: '-i' }
},
{
personName: { $regex: _personName, $options: '-i' }
},
{
"client._id": _clientID
},
{
isDeleted: { $ne: true }
}];
objModel.find({ $and: _searchQRY }, function (err, results) {
res.json({ status: config.responseStatus, record: results })
});
In this i pass "_clientID" is blank(''). At that time i want to ignore that parameter and search on remains parameter.
You can do smth like
var _branchName = req.query.branchName;
var _personName = req.query.personName;
var _clientID = req.query.clientID;
var _searchQRY = [
{
branchName: { $regex: _branchName, $options: '-i' }
},
{
personName: { $regex: _personName, $options: '-i' }
},
{
isDeleted: { $ne: true }
}];
if (_clientID) {
_searchQRY.push(
{
"client._id": _clientID
}
);
}
objModel.find({ $and: _searchQRY }, function (err, results) {
res.json({ status: config.responseStatus, record: results })
});
I.e. include client._id in the search query only when you do specify it in the request.
What you can do is, when _clientID is blank, change its value to object like this
if (_clientID == '')
_clientID = { $exists : true};
This will match all the client._id when _clientID is empty string ''

Resources