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

fra*_*acz 5 java spring mongodb spring-data spring-data-mongodb

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

> db.names.find({})
{ "name": "John" }
{ "name": "Jack" }
{ "name": "Johny" }
{ "name": "Jenny" }
Run Code Online (Sandbox Code Playgroud)

我已经为此集合创建了 Spring 数据存储库:

public interface NameRepository extends MongoRepository<Name, ObjectId> {
    Collection<Name> findByNameLike(String name);
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

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
Run Code Online (Sandbox Code Playgroud)

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

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

但我的方法的行为不同:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

fra*_*acz 3

实际上,有一个简单的方法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("\\*", ".*");
    }
}
Run Code Online (Sandbox Code Playgroud)

其行为与 Spring Data 存储库相同。


2016 年 4 月 19 日更新

从 1.9.0.RELEASE 开始有一个MongoRegexCreator类提供了一个toRegularExpression方法。

String regex = MongoRegexCreator.INSTANCE
               .toRegularExpression(userString, Part.Type.EXISTS);
Run Code Online (Sandbox Code Playgroud)

  • 使用 Spring Data MongoDB 2.x,您可以使用:`String regex = MongoRegexCreator.INSTANCE.toRegularExpression(userString, MongoRegexCreator.MatchMode.CONTAINING);` (3认同)