Context:
I am trying to code the back end of an "Advanced Search" option
It is a project I’m coding to practice JS, MongoDB(Mongoose), Next, Node, Etc.
The Schema I’m using is the following:
House Schema:{
name:String,
address:{
street:String
city:String,
state:String
},
operations:{
rent:Boolean,
shortRent:Boolean,
purchase:Boolean,
agentRentPrice:Number,
agentShortRentPrice:Number,
agentSellingPrice:Number},
features:{
bathrooms:Number,
bedrooms:Number,
beds:Number,
amenities:[String],
},
}
Now, the FrontEnd sends the following info (in req.body):
query = {
name: null,
address: { city: null, state: null },
operations: {
rentAvailable: false,
purchaseAvailable: false,
shortRentAvailable: false,
agentRentPriceMin: null,
agentSellingPriceMin: null,
agentShortRentPriceMin: null,
agentRentPriceMax: null,
agentSellingPriceMax: null,
agentShortRentPriceMax: null,
},
features: {
bathroomsMin: null,
dormsMin: null,
bedsMin: null,
amenities: null,
},
}
Of course, those "null" values will be replaced with numbers or strings with the parameters introduced by the user.
With this object, I then declare another:
let queryObj = {
name: query.name,
address: { city: query.address.city, state: query.address.state },
operations: {
rentAvailable: query.operations.rentAvailable,
purchaseAvailable: query.operations.purchaseAvailable,
shortRentAvailable: query.operations.shortRentAvailable,
agentRentPrice: {
$gte: query.operations.agentRentPriceMin,
$lte: query.operations.agentRentPriceMax,
},
agentSellingPrice: {
$gte: query.operations.agentSellingPriceMin,
$lte: query.operations.agentSellingPriceMax,
},
agentShortRentPrice: {
$gte: query.operations.agentShortRentPriceMin,
$lte: query.operations.agentShortRentPriceMax,
},
},
features: {
bathrooms: { $gte: query.features.bathroomsMin },
dorms: { $gte: query.features.dormsMin },
beds: { $gte: query.features.bedsMin },
amenities: { $in: query.features.amenities },
},
}
Finally I reduce this object, removing any "null", "false", "" and "{}" values.
For example, the user searches for: house available for renting, in New York, with 2 bedrooms, with a pool, and max Rent price of $10.000
So, req.body.query will be
{
name: null,
address: { city: "New York", state: null },
operations: {
rentAvailable: true,
purchaseAvailable: false,
shortRentAvailable: false,
agentRentPriceMin: null,
agentSellingPriceMin: null,
agentShortRentPriceMin: null,
agentRentPriceMax: 10000,
agentSellingPriceMax: null,
agentShortRentPriceMax: null,
},
features: {
bathroomsMin: null,
dormsMin: 2,
bedsMin: null,
amenities: ["pool"],
},
}
Next, I declare
let queryObj = {
name: null,
address: { city: "New York", state: null },
operations: {
rentAvailable: true,
purchaseAvailable: false,
shortRentAvailable: false,
agentRentPrice: {
$gte: null,
$lte: 10000,
},
agentSellingPrice: {
$gte: null,
$lte: null,
},
agentShortRentPrice: {
$gte: null,
$lte: null,
},
},
features: {
bathrooms: { $gte: null },
dorms: { $gte: 2 },
beds: { $gte: null },
amenities: { $in: ["pool"] },
},
};
I have a function here that reduces this object (removing "false" "null" "" and "{}" values):
queryObj = {
address: { city: "New York" },
operations: {
rentAvailable: true,
agentRentPrice: {
$lte: 10000,
},
},
features: {
dorms: { $gte: 2 },
amenities: { $in: ["pool"] },
},
};
As you can see, "query" (and therefore "queryObj") will vary a lot; the user may or may not use any of the available search parameters, so (as i see it) it is not possible to "hard-code" the queryObj structure
I’ve tried using
Home.aggregate([{$match:queryObj}])
without success (returns no results).
Is it possible what I’m trying to do?
2
Answers
Try to use a function to build the filter:
A little verbose, but it is due to the fact that you don’t have a 1-on-1 correspondence between the attributes of the body and your filter’s properties.
You can solve this by creating the filter dynamically on the backend. Basically, you will start with an empty filter, and then you will check each user input, and add it to the filter if exists. That way, you don’t have to worry if the user will send multiple filters, or if it will not send filters at all. Everything will be added dynamically.