Spring数据Mongodb:QueryDsl Predicate和Criteria API的互操作性

Ben*_*lon 13 querydsl spring-data-mongodb

我在Spring Data Mongodb中使用QueryDSL谓词.但是,我面临的情况是我必须使用MongoTemplate查询API(例如过滤从Mongo获取的字段).这是一个简单的例子:

public Stream<MyModel> findSummary(Predicate predicate){
    Query query = new Query();
    query.fields.include("field1").include("field2");
    return mongoTemplate.stream(query, MyModel.class);
}
Run Code Online (Sandbox Code Playgroud)

我想将我的谓词转换为标准,以便我可以做类似的事情:

Query query = new Query();
query.addCriteria(XXXXX.toCriteria(predicate));
Run Code Online (Sandbox Code Playgroud)

但是我找不到这样的实用类.

我发现可以访问QueryDSL谓词,因此我开始实现自定义访问者(com.mysema.query.types.Visitor),但Criteria API并不是为此目的而设计的:例如实现简单的"和"运算符QueryDSL(com.mysema.query.types.Ops#AND)必须变成类似的东西

<result of left argument visit assumed to be a Criteria>.and("<path of right argument>").<operator of right argument>(<result of right argument visit>);
Run Code Online (Sandbox Code Playgroud)

有人可以提出一种方法来使QueryDSL Predicates和Spring Data Mongodb Query互操作吗?

谢谢

伯努瓦

Har*_*hit 3

我遇到了同样的问题,并且在互联网上没有找到该问题的任何解决方案。经过多次试验和错误,我已经实现了一个自定义解决方案,该解决方案在我的项目中运行良好,并且可能对其他人有帮助。

笔记

使用的版本:

  • spring-data-mongodb - 3.0.2.RELEASE
  • 查询DSL-4.3.1

实施

首先创建一个类,用修饰符扩展 org.springframework.data.mongodb.repository.support.SpringDataMongodbQuery并重写createQuery(Predicate predicate)方法public

public class CustomSpringDataMongodbQuery<T> extends SpringDataMongodbQuery<T> {

    public CustomSpringDataMongodbQuery(MongoOperations operations, Class<? extends T> type) {
        super(operations, type);
    }

    @Override
    public Document createQuery(Predicate predicate) {
        return super.createQuery(predicate);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在创建一个实现 org.springframework.data.mongodb.core.query.CriteriaDefinition.

public class DocumentCriteria implements CriteriaDefinition {

    private final Document criteriaObject;

    public DocumentCriteria(Document criteriaObject) {
        this.criteriaObject = criteriaObject;
    }

    @Override
    public Document getCriteriaObject() {
        return criteriaObject;
    }

    @Override
    public String getKey() {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用这两个类从谓词获取查询。

Document document = new CustomSpringDataMongodbQuery<>(mongoTemplate, MyModel.class).createQuery(predicate);
Query query = Query.query(new DocumentCriteria(document));
Run Code Online (Sandbox Code Playgroud)

投影查询

如果你想使用QClass字段进行投影,那么也是可以的。

在 CustomSpringDataMongodbQuery 类中,添加方法

public Query createQuery(Predicate filter, List<Path<?>> fields) {
    QTuple qTuple = Projections.tuple(fields.toArray(new Path[0]));
    return createQuery(filter, qTuple, QueryModifiers.EMPTY, Collections.emptyList());
}
Run Code Online (Sandbox Code Playgroud)

并传递路径列表(QClass 字段)以及谓词

使用投影和分页进行查询

您可以使用以下方法向上述方法添加分页

public Query createQuery(Predicate filter, List<Path<?>> fields, int page, int size, List<OrderSpecifier<?>> orderSpecifiers) {
    QTuple qTuple = Projections.tuple(fields.toArray(new Path[0]));
    QueryModifiers queryModifiers = new QueryModifiers((long) size, (long) (page - 1) * size);
    return createQuery(filter, qTuple, queryModifiers, orderSpecifiers);
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助每个想要使 QueryDSL 谓词和 Spring Data Mongodb 查询互操作的人。

欢迎任何建议!