Spring Data MongoDB:QueryDsl谓词和Criteria API的互操作性

17

我正在使用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);
}

我想将我的Predicate转换为Criteria,以便我可以执行类似以下的操作:

Query query = new Query();
query.addCriteria(XXXXX.toCriteria(predicate));

然而我找不到这样的实用程序类。

我发现QueryDSL谓词可以被访问,因此我开始实现一个自定义的访问者(com.mysema.query.types.Visitor),但是Criteria API并不是为此而设计的:例如,实现QueryDSL的简单“and”运算符(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>);

有人能提供一种方法,使QueryDSL谓词和Spring Data Mongodb查询相互配合吗?

谢谢

Benoit

1个回答

3

我遇到了同样的问题,但在互联网上没有找到任何解决方案。经过许多尝试和错误,我实现了一个自定义解决方案,在我的项目中工作良好,可能会帮助其他人。

注意事项

使用的版本:

  • spring-data-mongodb - 3.0.2.RELEASE
  • querydsl - 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);
    }
}

现在创建一个类,实现 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;
    }
}

现在你可以使用这两个类从谓词(Predicate)中获取查询(Query)。

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

投影查询

如果您想使用 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());
}

并传递Path(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);
}

希望这篇文章能帮到所有想要让QueryDSL谓词和Spring Data Mongodb查询相互配合的人。欢迎任何建议!

你好!你能提供一个使用示例吗?如何使用查询与投影和分页方法,并在投影中排除一个元素?是否有选项只提供我们想要排除的字段,还是我们必须在这里包含所有属性? - Andrew T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接