当前位置: 首页 > 知识库问答 >
问题:

spring-data-mongoDB可选查询参数

颜均
2023-03-14

我使用的是spring数据mongodb。

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

我有一个域类。

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
}

我的控制器:

@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;
    }

这里Key和username是可选的查询参数。

如果我通过其中任何一个,它应该返回具有给定密钥或用户名的匹配文档。

我的服务方式是:

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));
    }

存储库:

@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_one

共有2个答案

公羊灿
2023-03-14

不直接支持根据输入值筛选出查询的部分。不过,可以使用查询($)和运算符以及一点SpEL来完成。

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(详细信息请参见:json spel)可以避免重复类型名称。

龙骏
2023-03-14

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

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

@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);
    }

    ...
}

我知道这与数据库代码的运行时生成趋势背道而驰,但在我看来,它仍然是更具挑战性的数据库操作的最佳方法,因为它更容易看到实际发生的事情。

 类似资料:
  • 是否有其他选择-或者使用mongoTemplate是最好的选择? 谢谢

  • 问题内容: 我正在将spring-data mongo与基于JSON的查询方法一起使用,并且不确定如何在搜索查询中允许使用可选参数。 例如-说我有以下功能 -但是我不想应用名称正则表达式匹配,或者如果将NULL值传递给方法,则不希望应用日期范围限制。 目前看来,我可能必须使用mongoTemplate构建查询。 有没有其他选择-还是使用mongoTemplate是最佳选择? 谢谢 问题答案: 为了

  • 问题内容: 我想在存储库层中编写一些查询方法。此方法必须忽略空参数。例如: 在这种情况下,此方法必须返回Foo: 如果gooParam不为null。如果gooParam为null,则条件更改为: 有什么解决办法吗?有人能帮我吗? 问题答案: 来不及了。不确定 Bar 和 Goo 之间的关系。检查 Example是否 可以帮助您。 它为我工作。我有一个类似的情况,实体 用户 具有属性集,并且有基于属

  • GroupIdDeliveryStatusReport的结构 如果我不能恰当地描述,请原谅我。 我就是这样写的

  • 我想用spring Boot1.5执行过滤器列表的查询,我有必需的参数(用户名)和可选的参数(电子邮件),我如何在查询中分配可选的参数?@Query(“从User u中选择u.username LIKE:username和u.email=:email”)公共页面getUsers(@param(“username”)字符串username,@param(“email”)字符串email);http:

  • 问题内容: 我有以下POJO。 我正在尝试实现一个查询,该查询查找包含标签列表的所有。我尝试了以下方法: 但这仅在我传递给该方法的标记的完全匹配在Mongo中分配给该问题的标记的列表时才有效。例如,如果我在Mongo中有一个带有标签列表的问题,当我传递给该方法时,它不会返回。 我也尝试了以下方法: 但是我根本无法部署到我的servlet容器。(在这种情况下,我收到以下错误消息: 您能否建议如何实施