How to pass mongodb match conditions from node.js URL parameters - node.js

I have a webpage where users selects variables to filter and get database values. I tried passing the $match condition variables as below but i am not getting any results back
URL is : example.com?gender=M&date_from=20100101&date_to=201140101
I loop through the req.query to build the match condition string.
var matchQuery = [];
for (var param in req.query) {
qString = "{'" + param + "' : '" + req.query[param] + "'}";
matchQuery.push(qString);
}
var strmatchQuery = matchQuery.toString();
This outputs strmatchQuery as {'gender' : 'M'}, {'date_from' : '20100101'}, {'date_to' : '20140101'}
and then I call the mongodb aggregate function
dbmodel.aggregate( { $match: { $and: [ strmatchQuery ]} } , { $group : { _id : "$orderyear", totalorders : { $sum : 1 } } } )
But I dont get any results back. Any ideas?

function is_numeric(num) {
return !isNaN(num);
}
var matchQuery = [];
var qString = {};
for (var param in req.query) {
// You need objects in your query not strings so push objects
qString = {};
qString[param] = is_numeric(req.query[param]) ? Number(req.query[param]) : req.query[param];
matchQuery.push(qString);
}
// Removed the toString() function call
dbmodel.aggregate(
{$match: {$and: strmatchQuery}}, // Removed the array [ ]
{$group: {
_id: "$orderyear",
totalorders: {$sum: 1}}
}
);

Related

Mongoose Find() - Return all docs if query is undefined

I have mongoose Find code function , the query is recieved from params (Here currently hardcoded)
Suppose this as the query
var arrayOfCategories = [ '63073212ed3e0f85ccffc8cf' , '63073324ed3e0f85ccffc8ff']
var arrayOfSkill = []
This is my find code
const astro =await Astrologer.find({ 'category.astolCat_id' : {$in: arrayOfCategories},
'skills.astolSkill_id': { $in: arrayOfSkill}})
It works fine if I have a value in 'arrayOfSkill' array but I want it to ignore ''skills.astolSkill_id': { $in: arrayOfSkill}' and only query for arrayOfCategories if arrayOfSkill is blank. If arrayOfSkill is blank then I is returning blank array
Build up your query options progressively...
const query = {};
if (arrayOfCategories.length) {
query["category.astolCat_id"] = { $in: arrayOfCategories };
}
if (arrayOfSkill.length) {
query["skills.astolSkill_id"] = { $in: arrayOfSkill };
}
const astro =await Astrologer.find(query);
const filter = [{}]
arrayOfCategories.length > 0 && filter.push({'category.astolCat_id': {$in: arrayOfCategories}})
arrayOfSkill.length > 0 && filter.push({'skills.astolSkill_id': { $in: arrayOfSkill }})
const astro =await Astrologer.find({$and:filter})
If need, can be modified as ; find({$or: filter})

Build Mongo Query based on query parameters in url

I want to build a query as per the value available in the query parameters of the URL. The sample URL is :-
http://localhost:3000/api/user?page=&status=&search&role_id=
So when the status is available, the where clause related to it should work, the same for search and role_id.
I have tried to built a query where pagination part along with search parameter is working perfectly. But when I pass/set the keys of
query string, the query shows no results.
The query I have build so far is something like this:-
let {page, search, status, role_id} = req.query;
role_id = role_id ? role_id : null;
status = status ? status : null;
const currentPage = parseInt(page) || 1;
const perPage = recordsPerPage;
const userData = await User.find({
$and: [
{
$or : [
{username:{'$regex' : search, '$options' : 'i'}},
{email:{'$regex' : search, '$options' : 'i'}}
]
},
{
$or : [
{status : status}
]
},
{
$or : [
{role_id : role_id}
]
},
{
email: { $ne: 'xxxxx#gmail.com' }
}
]
})
.sort({_id : -1})
.populate('role_id')
.skip((currentPage - 1) * perPage).limit(perPage);
Instead of trying to rely on $or and $and in your query, you can just conditionally add fields to your query. A mongoose query is just passed an object and can be built outside the function call.
This way you won't have to worry about edge cases such as a user with status null being returned whenever you leave out the status field from your query.
let {page, search, status, role_id} = req.query;
role_id = role_id ? role_id : null;
status = status ? status : null;
const currentPage = parseInt(page) || 1;
const perPage = recordsPerPage;
const query ={
email: { $ne: 'xxxxx#gmail.com' }
}
if (status) {
query.status = status
}
if (role_id) {
query.role_id = role_id
}
if (search) {
query.username = {'$regex' : search, '$options' : 'i'}
delete query.email
query['$and'] = [
{ email: {'$regex' : search, '$options' : 'i'}},
{ email: { $ne: 'xxxxx#gmail.com' } }
]
}
const userData = await User.find(query)
.sort({_id : -1})
.populate('role_id')
.skip((currentPage - 1) * perPage).limit(perPage);
As an aside, I think a query with a $regex and a $ne on the same field (email in your example) may be very slow once executed on a large collection.

$regex is not working with integer value field

i tried to search data using $regex with mongoose but its not working with Number field.
here is my model.js
var transactionsSchema = new Schema({
user : Schema.Types.ObjectId,
amount : {type : Number}
});
here is my query
var condition = {
user:user,
amount:{ $regex: search}
};
Model.find(condition)..exec(function(err,res){
console.log(res);
});
i getting following error
Can't use $regex with Number.
then tried the following
var condition = {
user:user,
amount:{ "$where": "function() { return this.amount.toString().match(/"+search+"/) != null; }" }
};
Model.find(condition)..exec(function(err,res){
console.log(res);
});
its given following
Error: Can't use $where with Number.
now i changed my condition like this
var condition = {
user:user
}
condition["$where"] = "function() { return this.amount.toString().match(/"+search+"/) != null; }";
Model.find(condition)..exec(function(err,res){
console.log(res); //output []
});
its worked in mongo shell with accurate result but in mongoose query its return empty array

Query returning {} when it should return data

Im having trouble with a mongdb query returning {} from my node.js code.
Here is how I am building my query string in node.js javascript:
var idString = '' + firstId; // firstId = 1
var otheridString = '' + secondId; // secondId = 2
var users = { userid: { $in : [idString, otheridString] }};
But when I run this through nodeJS/mongo it returns {}
If I run this directly in the DB it returns the two rows
db.Users.find({ userid: { $in : ["1", "2"] }})
I think this has something to do with the userid's being strings, as if i run this query directly in the DB it returns {} also
db.Users.find({ userid: { $in : [1, 2] }})
Any help appreciated!
Please try this
var idString = firstId.toString(); // firstId = 1
var otheridString = secondId.toString(); // secondId = 2
var users = { userid: { $in : [idString, otheridString] }};

dynamically add fields to find() mongodb

Hi i am working with mongoDB , i am trying to crate a dynamic object and pass as an argument to the find()
my object is like this
Library
var search = {};
if(data.orderId) {
search["_id"] = { $in: data.orderId.split(",") } ;
}if(data.path) {
search["stops.districtId"] = data.path;
}if(data.special) {
search["special.option"] = { $in: data.special.split(",") } ;
}if(data.userInfo) {
search["UserId"] = data.userInfo;
}
then i will pass my search objet to the query like this
Model
var col = db.collection( CustomerOrderModel.collection() );
col.find(
{
serviceType:data.serviceType,
**search**
}
).skip(data.skip).limit(data.limit).sort(data.sort).toArray(function(err, res) {
if (err) {
reject( err );
} else {
resolve( res );
}
});
the problem here is when i console.log my search object i can see
'special.option': { '$in': [ 'ROUND_TRIP' ] } }
my $in is wrapped with quotes . so my query doesn't work .
if i directly type "special.option": { $in: [ 'ROUND_TRIP' ] } } in my query it is working correctly .
i m trying to built this search object because i have multiple fields to search with complex logic . i don't want to do these in my
model , so i wil create the search object in my library .
is there any possible ways to this , thanks in advance .
You should make the search object part of the query by adding the extra filters into the search object. As you are currently doing
col.find({
serviceType:data.serviceType,
search
})
this is interprated as
col.find({
serviceType:data.serviceType,
{ 'special.option': { '$in': [ 'ROUND_TRIP' ] } }
})
You should be able to add the serviceType filter to your existing search object using the square bracket notation as follows:
search["serviceType"] = data.serviceType;
then you can pass that object in your query:
var col = db.collection( CustomerOrderModel.collection() );
search["serviceType"] = data.serviceType;
col.find(search)
.skip(data.skip)
.limit(data.limit)
.sort(data.sort)
.toArray(function(err, res) {
if (err) { reject( err ); }
else { resolve( res ); }
});
That is not the problem.
console.log({ "special.option": { $in: [ 'ROUND_TRIP' ] } });
gives
{ 'special.option': { '$in': [ 'ROUND_TRIP' ] } }
so this is correct.
In your code you just write **search** in the most critical part, but try this:
search["serviceType"] = data.serviceType;
col.find( search )

Resources