多选择下拉框组合查询MongoDB:替代if-else的优化方案问询
Hey there! Let's fix that unwieldy if-else mess you're dealing with. Managing 16 combinations of filter states with conditionals is a maintenance nightmare—especially when you need to add new filters later. Here's a clean, scalable approach that eliminates all those redundant conditionals.
The Core Idea
Your problem boils down to two consistent tasks for each filter:
- If the filter isn't set to "all", add its corresponding field to the query.
- Build the collection name based on which filters are not set to "all" (since your collection names suffix with the non-"all" filters).
We can abstract each filter's behavior into reusable configuration, then dynamically process these configs to handle both tasks in one loop.
Step 1: Define Filter Metadata
First, create a simple structure to store each filter's key details. We'll use a Java record (for clean, immutable data) but you could use a regular class or even a Map if needed:
// A record to hold all critical info for each filter record FilterConfig( Supplier<Boolean> isAllSelected, // Checks if filter is set to "all" Supplier<List<String>> getValues, // Fetches the selected options String collectionSuffix, // Suffix to use in the collection name String queryField // MongoDB field name for the filter ) {}
Step 2: Initialize Filter Configurations
Map each of your 4 filters to this metadata. Make sure the order matches the suffix order in your existing CollectionNames enum (e.g., MARKET comes before CMTS, etc.—this ensures your collection names stay consistent with existing code):
private void constructQuery(MongoQuery query, AnalysisFilter filter) { // Base query filters (these stay the same regardless of user selection) query.addFilterField("_id.operator", MongoQuery.OP_EQUALS, "alpha"); query.addFilterField("_id.month_year", MongoQuery.OP_IN, getListOfMonthYear(filter)); // Initialize all filter configurations in order of your collection name suffixes List<FilterConfig> filterConfigs = List.of( new FilterConfig(filter::getAllMarket, filter::getMarket, "MARKET", "_id.market"), new FilterConfig(filter::getAllCmts, filter::getCmts, "CMTS", "_id.cmts"), new FilterConfig(filter::getAllNode, filter::getNode, "NODE", "_id.node"), new FilterConfig(filter::getAllPackage, filter::getSubscriberPackage, "PACKAGE", "_id.package") );
Step 3: Dynamically Build Collection Name & Query
Loop through the configs to collect non-"all" filters, add their query conditions, and assemble the collection name:
List<String> nonAllSuffixes = new ArrayList<>(); for (FilterConfig config : filterConfigs) { if (!config.isAllSelected().get()) { // Add the filter condition to the query query.addFilterField(config.queryField(), MongoQuery.OP_IN, config.getValues().get()); // Collect the suffix for the collection name nonAllSuffixes.add(config.collectionSuffix()); } } // Build the full collection name StringBuilder collectionNameBuilder = new StringBuilder(CollectionNames.ME_USAGE_MONTH_YEAR.toString()); if (!nonAllSuffixes.isEmpty()) { collectionNameBuilder.append("_").append(String.join("_", nonAllSuffixes)); } String collectionName = collectionNameBuilder.toString(); // If you want to use the CollectionNames enum (safer than raw strings), uncomment this: // CollectionNames targetCollection = CollectionNames.valueOf(collectionName); // String collectionName = targetCollection.toString(); // Rest of your logic using collectionName... }
Why This Works Better
- No More Redundant Code: Adding a new filter only requires adding one line to the
filterConfigslist—no need to write dozens of new if-else blocks. - Consistent Naming: Eliminates typos in collection names since we're using predefined suffixes.
- Readable & Maintainable: All filter logic is centralized in the configs, making it easy to modify or debug individual filters.
- Scalable: Works for any number of filters, not just 4.
内容的提问来源于stack exchange,提问作者Debashish Sen

