首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >spring-data-mongodb可选查询参数

spring-data-mongodb可选查询参数
EN

Stack Overflow用户
提问于 2015-06-15 09:00:48
回答 2查看 3.4K关注 0票数 6

我在使用。

我希望通过在查询中传递一些可选参数来查询数据库。

我有一个域类。

代码语言:javascript
复制
public class Doc {  
    @Id
    private String id;

    private String type;

    private String name;

    private int index;  

    private String data;

    private String description;

    private String key;

    private String username;
    // getter & setter
}

我的控制器:

代码语言:javascript
复制
@RequestMapping(value = "/getByCategory", method = RequestMethod.GET, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
    public Iterable<Doc> getByCategory(
            @RequestParam(value = "key", required = false) String key,
            @RequestParam(value = "username", required = false) String username,
            @RequestParam(value = "page", required = false, defaultValue = "0") int page,
            @RequestParam(value = "size", required = false, defaultValue = "0") int size,
            @RequestParam(value = "categories") List<String> categories)
            throws EntityNotFoundException {
        Iterable<Doc> nodes = docService.getByCategory(key, username , categories, page, size);
        return nodes;
    }

这里,用户名是可选的查询参数。

如果我传递其中任何一个,它应该用给定的键或用户名返回匹配的文档。

我的服务方法是:

代码语言:javascript
复制
public Iterable<Doc> getByCategory(String key, String username, List<String> categories, int page, int size) {

        return repository.findByCategories(key, username, categories, new PageRequest(page, size));
    }

储存库:

代码语言:javascript
复制
@Query("{ $or : [ {'key':?0},{'username':?1},{categories:{$in: ?2}}] }")    
List<Doc> findByCategories(String key, String username,List<String> categories, Pageable pageable);

但是,通过使用上面的查询,它不会返回具有给定密钥或用户名的文档。我的问题出了什么问题?

我就是这样提出请求的http://localhost:8080/document/getByCategory?key=key

EN

回答 2

Stack Overflow用户

发布于 2015-07-01 14:20:43

就我个人而言,我会抛弃接口驱动的存储库模式,创建一个@Autowire是MongoTemplate对象的DAO,然后使用Criteria查询DB。这样,您就有了清晰的代码,而不是扩展@Query注释的功能。

所以,像这样的东西(未经测试的,伪代码):

代码语言:javascript
复制
@Repository
public class DocDAOImpl implements DocDAO {
    @Autowired private MongoTemplate mongoTemplate;

    public Page<Doc> findByCategories(UserRequest request, Pageable pageable){
        //Go through user request and make a criteria here
        Criteria c = Criteria.where("foo").is(bar).and("x").is(y); 
        Query q = new Query(c);
        Long count = mongoTemplate.count(q);

        // Following can be refactored into another method, given the Query and the Pageable.
        q.with(sort); //Build the sort from the pageable.
        q.limit(limit); //Build this from the pageable too
        List<Doc> results = mongoTemplate.find(q, Doc.class);
        return makePage(results, pageable, count);
    }

    ...
}

我知道这与运行时生成DB代码的趋势背道而驰,但在我看来,对于更具挑战性的DB操作来说,这仍然是最好的方法,因为它的负载更容易查看到底发生了什么。

票数 1
EN

Stack Overflow用户

发布于 2022-05-12 09:34:33

不直接支持根据输入值筛选出部分查询。不过,可以使用@Query$and操作符和一些SpEL来完成。

代码语言:javascript
复制
interface Repo extends CrudRepository<Doc,...> {

  @Query("""
         { $and : [ 
            ?#{T(com.example.Repo.QueryUtil).ifPresent([0], 'key')}, 
            ?#{T(com.example.Repo.QueryUtil).ifPresent([1], 'username')},
            ... 
         ]}
         """)
  List<Doc> findByKeyAndUsername(@Nullable String key, @Nullable String username, ...)

  class QueryUtil {
    public static Document ifPresent(Object value, String property) {
      if(value == null) {
        return new Document("$expr", true); // always true
      }
      return new Document(property, value); // eq match
    }
  }

  // ...
}

与通过T(...)类型表达式寻址目标函数不同,编写EvaluationContextExtension (参见:贾森斯派尔获取详细信息)允许一次又一次地重复类型名称。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30841152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档