Java多条件搜索结果异常:循环后仅保留最后一次搜索结果
食谱多条件搜索结果丢失问题解决
问题描述
开发支持多搜索词和多搜索类型的食谱搜索页面时,遇到结果丢失问题:单个搜索条件可正常返回结果,但多条件搜索时,页面仅展示最后一次搜索的结果。当前搜索词和搜索类型能正常传递,但无法聚合所有符合条件的结果并返回给页面。
现有代码
控制器代码
@PostMapping("adv-search/results") public String displayAdvancedSearchResults(Model model , @RequestParam String searchType, @RequestParam String searchTerm) { Iterable<Recipe> recipes = null; String[] searchTerms = searchTerm.split(","); String[] searchTypes = searchType.split(","); for (int i=0; i < searchTerms.length; i++) { String sTe = searchTerms[i]; String sTy = searchTypes[i]; if (sTe.toLowerCase().equals("all") || sTe.equals("")){ recipes = RecipeRepository.findAll(); } else { recipes = RecipeData.findByColumnAndValue(sTy, sTe, RecipeRepository.findAll()); } } model.addAttribute("columns", columnChoices); model.addAttribute("title", "Recipes with " + columnChoices.get(searchType) + ": " + searchTerm); model.addAttribute("recipes", recipes); return "adv-search"; }
RecipeData类代码
public class RecipeData { public static ArrayList<Recipe> findByColumnAndValue(String column, String value, Iterable<Recipe> allRecipes) { ArrayList<Recipe> results = new ArrayList<>(); if (value.toLowerCase().equals("all")){ return (ArrayList<Recipe>) allRecipes; } if (column.equals("all")){ results = findByValue(value, allRecipes); return results; } for (Recipe recipe : allRecipes) { String aValue = getFieldValue(recipe, column); if (aValue != null && aValue.toLowerCase().contains(value.toLowerCase())) { results.add(recipe); } } return results; } public static String getFieldValue(Recipe recipe, String fieldName) { String theValue; if (fieldName.equals("name")){ theValue = recipe.getName(); System.out.println(recipe.getName()); } else if (fieldName.equals("ingredients")){ theValue = recipe.getIngredientList().toString(); System.out.println(recipe.getIngredientList().toString()); } else { //prints [com.launchcode.recipeproject.models.Tag@20] instead of tags theValue = recipe.getTags().toString().toString(); System.out.println(recipe.getTags().toString().toString()); } return theValue; } public static ArrayList<Recipe> findByValue(String value, Iterable<Recipe> allRecipes) { String lower_val = value.toLowerCase(); ArrayList<Recipe> results = new ArrayList<>(); for (Recipe recipe : allRecipes) { if (recipe.getName().toLowerCase().contains(lower_val)) { results.add(recipe); } else if (recipe.getIngredientList().toString().toLowerCase().contains(lower_val)) { results.add(recipe); } else if (recipe.getTags().toString().toLowerCase().contains(lower_val)) { results.add(recipe); } else if (recipe.toString().toLowerCase().contains(lower_val)) { results.add(recipe); } } return results; } }
问题根源
- 循环中每次都会覆盖
recipes变量的引用,最终仅保留最后一次循环的查询结果,未实现多条件结果聚合。 - 每次查询都基于全量食谱数据(
RecipeRepository.findAll()),而非上一次的过滤结果,导致多条件无法叠加过滤。
修复方案
1. 修改控制器逻辑,实现多条件叠加过滤(交集逻辑)
将结果存储改为List<Recipe>,初始化为全量数据,之后每次循环基于当前结果进行过滤,保留符合所有条件的食谱:
@PostMapping("adv-search/results") public String displayAdvancedSearchResults(Model model, @RequestParam String searchType, @RequestParam String searchTerm) { List<Recipe> recipes = new ArrayList<>(); String[] searchTerms = searchTerm.split(","); String[] searchTypes = searchType.split(","); // 初始化结果为全量食谱 recipes.addAll(RecipeRepository.findAll()); for (int i = 0; i < searchTerms.length; i++) { String sTe = searchTerms[i].trim(); // 去除输入空格,避免无效搜索词 String sTy = searchTypes[i].trim(); if (sTe.toLowerCase().equals("all") || sTe.isEmpty()) { // 该条件为"all"或空,跳过过滤,保持当前结果 continue; } // 基于当前结果进行下一轮过滤,而非全量数据 recipes = RecipeData.findByColumnAndValue(sTy, sTe, recipes); } model.addAttribute("columns", columnChoices); model.addAttribute("title", "Recipes with " + columnChoices.get(searchType) + ": " + searchTerm); model.addAttribute("recipes", recipes); return "adv-search"; }
2. 优化标签搜索显示(可选)
原getFieldValue方法中,recipe.getTags().toString()会输出对象地址而非标签名称,需重写Tag类的toString()方法:
public class Tag { // ... 原有属性和方法 @Override public String toString() { return this.getName(); // 假设Tag类有getName()方法返回标签名称 } }
3. 若需并集逻辑(满足任意条件)
如果需要展示符合任意一个搜索条件的食谱,修改控制器中的循环逻辑,将每次查询结果合并并去重:
// 初始化空集合,自动去重 Set<Recipe> recipeSet = new HashSet<>(); for (int i = 0; i < searchTerms.length; i++) { String sTe = searchTerms[i].trim(); String sTy = searchTypes[i].trim(); if (sTe.toLowerCase().equals("all") || sTe.isEmpty()) { recipeSet.addAll(RecipeRepository.findAll()); continue; } List<Recipe> currentResults = RecipeData.findByColumnAndValue(sTy, sTe, RecipeRepository.findAll()); recipeSet.addAll(currentResults); } // 转换为List传给页面 List<Recipe> recipes = new ArrayList<>(recipeSet);
内容的提问来源于stack exchange,提问作者user22311577
相关产品推荐
相关产品推荐

