$or Operator in Mongoose - node.js

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 } },
],
};

Related

How to flatten a nested mongoose 'find' query only on the first level

I have written a mongoose find query for the following schema
{
_id: "12345678",
date: 2021-08-16T04:26:18.000Z,
en: {
title: "some title",
subtitle: "some subtitle",
content: [
{
main: "some content",
},
],
}
}
I want to return _id, date and everything inside en key, so it would look like this:
{
_id: "12345678",
date: 2021-08-16T04:26:18.000Z,
title: "some title",
subtitle: "some sub title",
content: [
{
main: "some content",
},
],
}
I'm wondering if I can do that using select populate or any other method in mongoose. I'm using express js in my backend.
This is my current query:
exports.post_list = function (req, res, next) {
PostSchema.find(
{ visible: true },
{ visible: 0, es: 0 },
function (err, posts) {
if (err) return next(err);
res.send(posts);
}
);
};
There is a way to do this for sure
Try this
let searchValue="";
let requestCondition = [{Add your conditions here}];//_id:1
let regex = new RegExp(searchValue,'i');//i is a flag
requestCondition.push({$or: [
{ "_id": { $regex: regex } },
{ "_date": { $regex: regex } },
{ "_title": { $regex: regex } },
{ "subtitle": { $regex: regex } },
{ "contents": { $regex: regex } }
]});
}
requestCondition = {$and: requestCondition}
let result = await modelName.find(requestCondition)
.sort( { _id : -1 } )
.skip(pg.skip)
.limit(pg.pageSize)
.exec();
let total = await modelName.find(requestCondition).countDocuments();
return {
"pagination":CallYourPaginationObject(pg.pageNo,pg.pageSize,pg.skip,total,result.length),
"data":result
};
}
you can write a recursive function to do this. or you can simply write a projection in your mongodb query to return just the en and _id.
for additinal information about mongo project read this article.
https://docs.mongodb.com/manual/reference/operator/aggregation/project/
I found the solution for my problem. Thanks to Muhammad Mujtaba Shafique and Amir Almian for their comments
PostSchema.find(
{ visible: true },
{
_id: 1,
date: 1,
title: '$en.title',
subtitle: '$en.subtitle',
content: '$en.content',
},
function (err, posts) {
if (err) return next(err);
res.send(posts);
}
);

check an array of string value with array of object in mongodb

I have array of strings like this
let fromHour = ['2.5','3','3.5']
let toHour = ['2.5','3','3.5']
I have an array of object saved in mongoDB
timeRange = [
{
from:'2.5',
to:'3'
},
{
from:'3',
to:'3.5'
}
]
I want to check if any of my array of string value exist in that object value
I have tried this but it give me this error ( Unrecognized expression '$match' )
checkAppoint = await Appointment.aggregate([
{
$project: {
date: myScheduleFinal[k].date,
status: { $in: ['pending', 'on-going'] },
timeRange: {
'$match': {
'from': { $in: fromHolder },
'to': { $in: toHolder },
},
},
},
},
]);
also I have tried this solution and it work for me but it take to much time so I am trying this with aggregate
checkAppoint = await Appointment.findOne({
date: myScheduleFinal[k].date,
status: { $in: ['pending', 'on-going'] },
timeRange:{$elemMatch:{
from:{$in:fromHolder},
to:{$in:toHolder}
}}
});
So anyone have a solution for that
Just try $elemMatch and $in operators,
using find() method
checkAppoint = await Appointment.find({
timeRange: {
$elemMatch: {
from: { $in: fromHour },
to: { $in: toHour }
}
}
})
Playground
using aggregate() method
checkAppoint = await Appointment.aggregate([
{
$match: {
timeRange: {
$elemMatch: {
from: { $in: fromHour },
to: { $in: toHour }
}
}
}
}
])
Playground
So I have found a way around to solve this problem and I will share the solution I used
First I want to minimize my request to mongodb so I am now making just one request that bring all the appointment with the required date
and I want to make it this way because my fromHour and toHour array will change many time through single request
helperArray => contains all the day I want to check it's range
let checkAppoint = await Appointment.find({
date: { $in: helperArray },
status: { $in: ['pending', 'on-going'] },
});
now inside my for loop I will go through that data
checkAppoint.filter((singleAppoint) => {
if (singleAppoint._doc.date === myScheduleFinal[k].date) {
singleAppoint._doc.timeRange.map((singleTime) => {
if (fromHolder.includes(singleTime.from)) {
busy = true;
}
});
}
});

Mongoose: Is it possible to make a query on all jsons that contain a substring?

I'm using mongoose and my schema is:
const DeliverySchema = new mongoose.Schema({
startPlace:{type: String,required: true},
endPlace:{type: String,required: true},
});
Assuming that the start and end fields contain places in google format: street and city. Is it possible to make a query given only the city and which returns all the JSON that have that city in start or end as substring?
So if my record is:
startPlace:"Milano, MI, Italia",
endPlace:"Roma,RM,Italia"
And my query has parameter:
startPlace:"Milano"
It return me the JSON.
Thank you so much.
DeliverySchema.aggregate([
{
$match: {
$or: [
{
startPlace: {
$regex: "Milano, ?.+, ?.+"
}
},
{
endPlace: {
$regex: "Milano, ?.+, ?.+"
}
}
]
}
}
])
db.collection.aggregate([{
$match: {
$or: [{
startPlace: {
$regex: ".*Milano.*"
}
},
{
endPlace: {
$regex: ".*Milano.*"
}
}
]
}
}])
Mongo Playground

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 ''

How to use $regex in mongodb aggregation query within $match

I am trying to use the $regex within $match, its not returning the matching documents.
db.collection('MyCollection', function (err, collection) {
collection.aggregate([
{ $match: { 'Code': 'Value_01', 'Field2': { $regex: '/Value_2/g' } } },
{ $project: {
_id: 1,
CodeNumber: '$Code',
FieldName2: '$Field2'
}
}
], function (err, Result_doc) {
console.log(Result_doc);
}
});
Can anyone tell me where its going wrong or the correct syntax?
I even tried with replacing the
'Field2': { $regex: /Value_2/g }
As it says in the $regex docs you linked to, the two ways to do this are:
Field2: /Value_2/g
OR
Field2: { $regex: 'Value_2', $options: 'g' }
But I also tried your second attempt of 'Field2': { $regex: /Value_2/g } and that worked as well.
BTW, the g regex option doesn't make sense in this context as you just need one match anyway. Note that it isn't even listed in the $regex docs.
I got it working with the following code:
var Value_match = new RegExp('Value_2');
db.collection('MyCollection', function (err, collection) {
collection.aggregate([
{ $match: { Code: 'Value_01', Field2: { $regex: Value_match } } },
{ $project: {
_id: 1,
CodeNumber: '$Code',
FieldName2: '$Field2'
}
}
], function (err, Result_doc) {
console.log(Result_doc);
}
});
On pushing the object content to console using console.dir(Value_match) it prints out '/Value_2/'

Resources