java - Spring 如何在 mongo 中构建它的 like* 查询?

标签 java spring mongodb spring-data spring-data-mongodb

我的 Mongo 数据库中有以下文档(跳过了 _ids):

> db.names.find({})
{ "name": "John" }
{ "name": "Jack" }
{ "name": "Johny" }
{ "name": "Jenny" }

我已经为这个集合创建了 Spring Data 存储库:

public interface NameRepository extends MongoRepository<Name, ObjectId> {
    Collection<Name> findByNameLike(String name);
}

结果如下:

nameRepository.findByNameLike("John"); // John, Johny
nameRepository.findByNameLike("John$"); // John
nameRepository.findByNameLike("J*ny"); // Johny, Jenny
nameRepository.findByNameLike("Jo?*ny"); // Johny, Jenny
nameRepository.findByNameLike("Jo[]]?*ny"); // empty, without error

所以它的行为就像一个智能正则表达式。现在我想自己实现这样的行为:

class MyNameRepository {
    MongoOperations mongoOperations; // injected

    public Collection<Name> findByName(String like) {
        Query query = new Query();
        query.addCriteria(Criteria.where("name").regex(like));
        return mongoOperations.find(query, Name.class)
    }
}

但是我的方法的行为是不同的:

myNameRepository.findByName("John"); // John, Johny
myNameRepository.findByName("John$"); // John
myNameRepository.findByName("J*ny"); // empty, without error
myNameRepository.findByName("Jo?*ny"); // error (invalid regex)
myNameRepository.findByName("Jo[]]?*ny"); // error (invalid regex)

因此,我的自定义方法的工作方式与我在 Spring 数据存储库中定义的 findByNameRegex 方法完全相同。如何实现 findByNameLike 行为?

为什么我需要这个:当我需要按许多属性过滤我的 Collection 时(例如,仅按姓名、按姓名和姓氏、按姓名和邮政编码、按姓名、姓氏和邮政编码等),我更容易支持查询作为参数,而不是在存储库中创建许多非常长的命名方法。

最佳答案

其实有个简单的方法toLikeRegex将所有 * 转换为 .*。连同捕获无效的正则表达式,我的自定义实现可能如下所示:

class MyNameRepository {
    MongoOperations mongoOperations; // injected

    public Collection<Name> findByName(String like) {
        try{
            Query query = new Query();
            query.addCriteria(Criteria.where("name").regex(toLikeRegex(like)));
            return mongoOperations.find(query, Name.class);
        } catch(PatternSyntaxException e) {
            return Collections.emptyList();
        }
    }

    private String toLikeRegex(String source) {
        return source.replaceAll("\\*", ".*");
    }
}

并且行为与 Spring Data 存储库相同。


2016 年 4 月 19 日更新

有一个MongoRegexCreator自 1.9.0.RELEASE 起提供 toRegularExpression 方法的类。

String regex = MongoRegexCreator.INSTANCE
               .toRegularExpression(userString, Part.Type.EXISTS);

关于java - Spring 如何在 mongo 中构建它的 like* 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26144251/

相关文章:

java - 使 Spring Tool Suite 生成的 Web 应用程序在独立的 Tomcat 服务器上运行

javascript - 如何使用 Mongoose 检查字符串是否与数组的元素匹配

php - PHP中mongodb聚合中的Substr

java - 如何使用java授予文件和文件夹700和770权限

java - 如何删除Android线程中使用的final变量

java - 应用程序意外停止。由 : Java. lang.NullPointerException 引起的错误

java - 在Spring Boot中定位/resource/目录下的静态文件

java - Hibernate Validation i18n(日语)显示不佳(乱码)

java - 用于异步客户端到客户端消息传递的库

mongodb - 排除 MongoDB 中嵌入文档的单个字段以外的所有字段