Spring Boot MongoDB价格范围查询API问题排查求助
问题排查:Spring Boot MongoDB价格区间查询接口错误
问题描述
开发对接MongoDB Atlas集群的Spring Boot API,目标是实现根据动态传入的最小、最大价格值返回对应商品的接口。目前怀疑问题出在@Query和@PathVariable的使用上,考虑改用@RequestParam传递参数,但不确定Repository中@Query该如何调整,请求排查错误。
现有代码
Repository代码
package com.webshoppingbackend.springboot.repository; import java.util.List; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.Query; import com.webshoppingbackend.springboot.model.WebShoppingItem; public interface WebShoppingRepository extends MongoRepository<WebShoppingItem, String> { @Query("{category:?0}") List<WebShoppingItem> getItemsByCategory(String category); @Query("{brand:?0}") List<WebShoppingItem> getItemsByBrand(String brand); @Query("{price:{$lt:?0,$gt:?1}}") List<WebShoppingItem> getItemsBasedOnPrice(long higherPrice, long lowerPrice); }
Controller代码
package com.webshoppingbackend.springboot.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.webshoppingbackend.springboot.model.WebShoppingItem; import com.webshoppingbackend.springboot.services.WebShoppingService; @RestController @RequestMapping("/webshopping") public class WebShoppingController { @Autowired private WebShoppingService service; @GetMapping public List<WebShoppingItem> getAllItems() { return service.getWebShoppingItems(); } @GetMapping("/{itemId}") public WebShoppingItem getItem(@PathVariable String itemId) { return service.getItemById(itemId); } @GetMapping("/category/{category}") public List<WebShoppingItem> getItemsByCategory(@PathVariable String category) { return service.getItemsByCategory(category); } @GetMapping("/brand/{brand}") public List<WebShoppingItem> getItemsByBrand(@PathVariable String brand) { return service.getItemsByBrand(brand); } @GetMapping("/{price}") public List<WebShoppingItem> getItemsBasedOnPriceRange(@PathVariable long higherPrice, @PathVariable long lowerPrice) { return service.getItemsBasedOnPriceRange(higherPrice, lowerPrice); } @PostMapping @ResponseStatus(HttpStatus.CREATED) public WebShoppingItem addItem(@RequestBody WebShoppingItem webShoppingItem) { return service.addToWebShoppingItems(webShoppingItem); } @PutMapping public WebShoppingItem modifyItem(@RequestBody WebShoppingItem webShoppingItem) { return service.updateWebShoppingItem(webShoppingItem); } @DeleteMapping("/{itemId}") public String deleteItem(@PathVariable String itemId) { return service.deleteWebShoppingItem(itemId); } }
Service代码
package com.webshoppingbackend.springboot.services; import java.util.List; import java.util.UUID; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.webshoppingbackend.springboot.model.WebShoppingItem; import com.webshoppingbackend.springboot.repository.WebShoppingRepository; @Service public class WebShoppingService { @Autowired private WebShoppingRepository repository; // CRUD public WebShoppingItem addToWebShoppingItems(WebShoppingItem webShoppingItem) { webShoppingItem.setItemId(UUID.randomUUID().toString().split("-")[0]); return repository.save(webShoppingItem); } public List<WebShoppingItem> getWebShoppingItems() { return repository.findAll(); } public WebShoppingItem getItemById(String itemId) { return repository.findById(itemId).get(); } public List<WebShoppingItem> getItemsByCategory(String category) { return repository.getItemsByCategory(category); } public List<WebShoppingItem> getItemsByBrand(String brand) { return repository.getItemsByBrand(brand); } public List<WebShoppingItem> getItemsBasedOnPriceRange(long higherPrice, long lowerPrice) { return repository.getItemsBasedOnPrice(higherPrice, lowerPrice); } public WebShoppingItem updateWebShoppingItem(WebShoppingItem webShoppingItem) { WebShoppingItem itemToBeUpdated = repository.findById(webShoppingItem.getItemId()).get(); itemToBeUpdated.setCategory(webShoppingItem.getCategory()); itemToBeUpdated.setProductName(webShoppingItem.getProductName()); itemToBeUpdated.setImageSource(webShoppingItem.getImageSource()); itemToBeUpdated.setBrand(webShoppingItem.getBrand()); itemToBeUpdated.setPrice(webShoppingItem.getPrice()); itemToBeUpdated.setRating(webShoppingItem.getRating()); itemToBeUpdated.setShippingCharges(webShoppingItem.getShippingCharges()); itemToBeUpdated.setProductDetails(webShoppingItem.getProductDetails()); return repository.save(itemToBeUpdated); } public String deleteWebShoppingItem(String itemId) { repository.deleteById(itemId); return "Deleted Web Shopping Item"; } }
请求情况
使用Talend API Tester发送请求,路径为/webshopping/100/50,尝试传入最高价格100、最低价格50,但接口无法正确返回结果。
问题分析与修正方案
1. Controller路径与参数绑定错误
原Controller中@GetMapping("/{price}")仅定义了一个路径变量,但方法声明了两个@PathVariable,Spring无法正确解析参数,直接导致路径匹配失败。且价格区间属于查询过滤参数,不符合REST路径变量的使用场景,应改用@RequestParam传递。
修改Controller中的价格区间接口:
@GetMapping("/price-range") public List<WebShoppingItem> getItemsBasedOnPriceRange( @RequestParam("minPrice") long minPrice, @RequestParam("maxPrice") long maxPrice) { return service.getItemsBasedOnPriceRange(maxPrice, minPrice); }
2. Repository中@Query的参数逻辑确认
原@Query("{price:{$lt:?0,$gt:?1}}")逻辑为price < 第一个参数(higherPrice)且price > 第二个参数(lowerPrice),逻辑本身正确,但参数顺序容易混淆。可以改用命名参数提升可读性:
修改Repository方法:
import org.springframework.data.repository.query.Param; // ... @Query("{price: {$gt: :#{#minPrice}, $lt: :#{#maxPrice}}}") List<WebShoppingItem> getItemsBasedOnPrice(@Param("minPrice") long minPrice, @Param("maxPrice") long maxPrice);
对应的Service方法同步调整参数顺序:
public List<WebShoppingItem> getItemsBasedOnPriceRange(long minPrice, long maxPrice) { return repository.getItemsBasedOnPrice(minPrice, maxPrice); }
3. 请求方式调整
修改后,请求URL格式应为/webshopping/price-range?minPrice=50&maxPrice=100,通过查询参数清晰传递最小和最大价格。
总结
@PathVariable适合标识资源唯一ID,查询过滤类参数(如价格区间)应使用@RequestParam;- 确保Repository中
@Query的参数顺序或命名与方法参数一致,避免逻辑错误; - 调整Controller接口的参数绑定方式后,使用正确的查询参数格式发送请求即可解决问题。
内容的提问来源于stack exchange,提问作者Akash
相关产品推荐
相关产品推荐

