Skip to content

Add rule-to-filter mapping #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: feature/rule-based-filtering
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions lib/queryrules.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ Query = { "States": { "$in": ["PA", "NJ", "DE", "MD", "NY", "WV", "VA", "OH"] }
Chip = Perennial
Keywords = Perennial
Query = { "Life Cycle Flags": { "$in": ["Perennial"] } }
Filters = { "Life Cycle Flags": ["Perennial"] }

[duration_Annual]
Chip = Annual
Keywords = Annual
Query = { "Life Cycle Flags": { "$in": ["Annual"] } }
Filters = { "Life Cycle Flags": ["Annual"] }

[duration_Biennial]
Chip = Biennial
Keywords = Biennial
Query = { "Life Cycle Flags": { "$in": ["Biennial"] } }
Filters = { "Life Cycle Flags": ["Biennial"] }

[MonarchsCheck]
Chip = Supports Monarchs
Expand All @@ -36,16 +39,19 @@ Query = { "Pollinator Flags": { "$in": ["Monarch Butterfly"] } }
Chip = Part Shade
Keywords = partial, Part Shade, Partial Shade, Filtered Light, Partial Sun, Part Sun
Query = { "Sun Exposure Flags": { "$in": ["Part Shade"] } }
Filters = { "Sun Exposure Flags": ["Part Shade"] }

[SunExposure_FullSun]
Chip = Full Sun
Keywords = Full Sun, All day sun, sun
Query = { "Sun Exposure Flags": { "$in": ["Full Sun"] } }
Filters = { "Sun Exposure Flags": ["Full Sun"] }

[SunExposure_Shade]
Chip = Shade
Keywords = Full Shade, Deep Shade, Shade, Shady location, Shade Tolerant
Query = { "Sun Exposure Flags": { "$in": ["Shade"] } }
Filters = { "Sun Exposure Flags": ["Shade"] }

[FallBlooming]
Chip = Fall Blooming
Expand All @@ -61,16 +67,19 @@ Query = { "Flowering Months": { "$regex": "mar|apr|may", "$options": "i" } }
Chip = Wet Soil
Keywords = Wet, Rain Garden, Puddles, Wet Feet, Wet Soil, Wet Dirt
Query = { "Soil Moisture Flags": { "$in": ["Wet"] } }
Filters = { "Soil Moisture Flags": ["Wet"] }

[SoilMoisture_Dry]
Chip = Dry Soil
Keywords = Dry, Cracks in Soil, Dry Soil, Dry Dirt
Query = { "Soil Moisture Flags": { "$in": ["Dry"] } }
Filters = { "Soil Moisture Flags": ["Dry"] }

[SoilMoisture_Moist]
Chip = Moist Soil
Keywords = Moist, Slightly Moist, Moist Soil, Slightly Wet
Query = { "Soil Moisture Flags": { "$in": ["Moist"] } }
Filters = { "Soil Moisture Flags": ["Moist"] }

[DroughtTolerance]
Chip = Drought Tolerant
Expand All @@ -81,96 +90,115 @@ Query = { "Plant Type Flags": { "$in": ["Drought Tolerant"] } }
Chip = Evergreen Plants
Keywords = Evergreen, Evergreen Trees, Trees that are evergreen
Query = { "Plant Type Flags": { "$in": ["Evergreen"] } }
Filters = { "Plant Type Flags": ["Evergreen"] }

[Tree]
Chip = Tree
Keywords = Tree
Query = { "Plant Type Flags": { "$in": ["Tree"] } }
Filters = { "Plant Type Flags": ["Tree"] }

[Shrub]
Chip = Shrub
Keywords = Shrub, Bush
Query = { "Plant Type Flags": { "$in": ["Shrub"] } }
Filters = { "Plant Type Flags": ["Shrub"] }

[Vine]
Chip = Vine
Keywords = Vine, Climbing, Climber
Query = { "Plant Type Flags": { "$in": ["Vine"] } }
Filters = { "Plant Type Flags": ["Vine"] }

[Fern]
Chip = Fern
Keywords = Fern
Query = { "Plant Type Flags": { "$in": ["Fern"] } }
Filters = { "Plant Type Flags": ["Fern"] }

[Grass]
Chip = Grass
Keywords = Grass, Grasses, Sedge, Sedges, Rush, Rushes
Query = { "Plant Type Flags": { "$in": ["Grass", "Sedge", "Rush"] } }
Filters = { "Plant Type Flags": ["Grass", "Sedge", "Rush"] }

[Hummingbirds]
Chip = Attracts Hummingbirds
Keywords = Hummingbird, Hummingbirds, Hummingbird-attracting
Query = { "Pollinator Flags": { "$in": ["Hummingbirds"] } }
Filters = { "Pollinator Flags": ["Hummingbirds"] }

[Butterflies]
Chip = Attracts Butterflies
Keywords = Butterfly, Butterflies
Query = { "Pollinator Flags": { "$in": ["Butterflies"] } }
Filters = { "Pollinator Flags": ["Butterflies"] }

[Bees]
Chip = Attracts Bees
Keywords = Bee, Bees, Bumblebee, Bumblebees, Honey Bee
Query = { "Pollinator Flags": { "$in": ["Bees"] } }
Filters = { "Pollinator Flags": ["Bees"] }

[RedFlower]
Chip = Red Flowers
Keywords = Red, Red Flower, Red Flowers, Red Blooms
Query = { "Flower Color Flags": { "$in": ["Red"] } }
Filters = { "Flower Color Flags": ["Red"] }

[BlueFlower]
Chip = Blue Flowers
Keywords = Blue, Blue Flower, Blue Flowers, Blue Blooms
Query = { "Flower Color Flags": { "$in": ["Blue"] } }
Filters = { "Flower Color Flags": ["Blue"] }

[YellowFlower]
Chip = Yellow Flowers
Keywords = Yellow, Yellow Flower, Yellow Flowers, Yellow Blooms
Query = { "Flower Color Flags": { "$in": ["Yellow"] } }
Filters = { "Flower Color Flags": ["Yellow"] }

[PurpleFlower]
Chip = Purple Flowers
Keywords = Purple, Purple Flower, Purple Flowers, Purple Blooms, Violet
Query = { "Flower Color Flags": { "$in": ["Purple"] } }
Filters = { "Flower Color Flags": ["Purple"] }

[WhiteFlower]
Chip = White Flowers
Keywords = White, White Flower, White Flowers, White Blooms
Query = { "Flower Color Flags": { "$in": ["White"] } }
Filters = { "Flower Color Flags": ["White"] }

[PinkFlower]
Chip = Pink Flowers
Keywords = Pink, Pink Flower, Pink Flowers, Pink Blooms
Query = { "Flower Color Flags": { "$in": ["Pink"] } }
Filters = { "Flower Color Flags": ["Pink"] }

[OrangeFlower]
Chip = Orange Flowers
Keywords = Orange, Orange Flower, Orange Flowers, Orange Blooms
Query = { "Flower Color Flags": { "$in": ["Orange"] } }
Filters = { "Flower Color Flags": ["Orange"] }

[GreenFlower]
Chip = Green Flowers
Keywords = Green, Green Flower, Green Flowers, Green Blooms
Query = { "Flower Color Flags": { "$in": ["Green"] } }
Filters = { "Flower Color Flags": ["Green"] }

[Superplant]
Chip = Super Plant
Keywords = Super, Super Plant, Superplant
Query = { "Superplant": true }
Filters = { "Superplant": ["Super Plant"] }

[Showy]
Chip = Showy
Keywords = Showy, Showy Flowers, Showy Blooms
Query = { "Showy": true }
Filters = { "Showy": ["Showy"] }

[FallColor]
Chip = Fall Color
Expand Down
45 changes: 45 additions & 0 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@ const version = fs.existsSync(versionFile)
? fs.readFileSync(versionFile, "utf8")
: "0";
const axios = require("axios");
const ini = require("ini");

// Load query rules from queryrules.ini at startup
const queryRulesPath = path.join(__dirname, "queryrules.ini");
let queryRules = {};
if (fs.existsSync(queryRulesPath)) {
const parsed = ini.parse(fs.readFileSync(queryRulesPath, "utf8"));
for (const [name, rule] of Object.entries(parsed)) {
try {
queryRules[name] = {
chip: rule.Chip,
keywords: String(rule.Keywords || "")
.split(/,\s*/)
.filter(Boolean),
query: JSON.parse(rule.Query),
filters: rule.Filters ? JSON.parse(rule.Filters) : undefined,
};
} catch (e) {
console.error(`Failed to parse query rule ${name}:`, e);
}
}
}

// Disabled for now because it causes confusion when we update the data
// const cache = {};
Expand Down Expand Up @@ -59,11 +81,31 @@ module.exports = async function ({ plants, nurseries }) {
});
return res.send(response.data);
});

// Provide query rules to the frontend
app.get("/api/v1/queryrules", (req, res) => {
res.json(queryRules);
});
app.get("/api/v1/plants", async (req, res) => {
try {
const fetchResults = req.query.results !== "0";
const fetchTotal = req.query.total !== "0";
const query = {};
const ruleChips = [];
const rulesParam = req.query.rules;
if (rulesParam) {
const names = Array.isArray(rulesParam)
? rulesParam
: String(rulesParam).split(/,/);
for (const name of names) {
const rule = queryRules[name];
if (rule) {
if (!query.$and) query.$and = [];
query.$and.push(rule.query);
ruleChips.push({ name, chip: rule.chip });
}
}
}
const sorts = {
"Sort by Common Name (A-Z)": {
"Common Name": 1,
Expand Down Expand Up @@ -437,6 +479,9 @@ module.exports = async function ({ plants, nurseries }) {
);
}
}
if (ruleChips.length) {
response.ruleChips = ruleChips;
}
// setCache(req, response);
return res.send(response);
} catch (e) {
Expand Down
Loading