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?
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.