如何在Java中使用QueryDSL、Spring-Data、MongoDB创建嵌入式谓词
使用QueryDSL针对MongoDB嵌套文档构建谓词
我来帮你搞定这个嵌套文档的QueryDSL谓词构建问题~首先得先对应你的Mongo文档结构,定义好实体类和QueryDSL的Q类(如果用了Spring Data MongoDB的QueryDSL支持,这些Q类会自动生成),大概结构如下:
// Rule实体 @Document public class Rule { @Id private String id; private String name; private List<ExpressionGroup> expressionGroups; // getter/setter } // ExpressionGroup实体 public class ExpressionGroup { private String type; private List<Expression> expressions; // getter/setter } // Expression实体 public class Expression { private String name; private List<String> values; // getter/setter } // 自动生成的Q类示例 public class QRule extends EntityPathBase<Rule> { public static final QRule rule = new QRule("rule"); public final StringPath id = createString("id"); public final StringPath name = createString("name"); public final ListPath<ExpressionGroup, QExpressionGroup> expressionGroups = this.<ExpressionGroup, QExpressionGroup>createList("expressionGroups", ExpressionGroup.class, QExpressionGroup.class, PathInits.DIRECT2); } public class QExpressionGroup extends EntityPathBase<ExpressionGroup> { public static final QExpressionGroup expressionGroup = new QExpressionGroup("expressionGroup"); public final StringPath type = createString("type"); public final ListPath<Expression, QExpression> expressions = this.<Expression, QExpression>createList("expressions", Expression.class, QExpression.class, PathInits.DIRECT2); } public class QExpression extends EntityPathBase<Expression> { public static final QExpression expression = new QExpression("expression"); public final StringPath name = createString("name"); public final ListPath<String, StringPath> values = this.<String, StringPath>createList("values", String.class, StringPath.class, PathInits.DIRECT2); }
接下来针对不同的查询需求,构建对应的谓词:
1. 查询包含特定name和value的Expression
比如要找所有expressions中存在name="name1"且包含value="VAL1"的Rule:
// 获取Q类实例 QRule qRule = QRule.rule; // 构建谓词:匹配expressionGroups数组中任意一个元素,其expressions数组中任意一个元素满足name和value条件 Predicate predicate = qRule.expressionGroups.any() .expressions.any() .name.eq("name1") .and(qRule.expressionGroups.any() .expressions.any() .values.contains("VAL1")); // 执行查询 List<Rule> rules = ruleRepository.findAll(predicate);
2. 按ExpressionGroup的Type筛选后查询表达式
比如要找type="WHEN"的ExpressionGroup下,存在name="name2"的Expression的Rule:
QRule qRule = QRule.rule; // 用lambda写法让嵌套逻辑更清晰 Predicate predicate = qRule.expressionGroups.any(group -> group.type.eq("WHEN") .and(group.expressions.any(expr -> expr.name.eq("name2"))) ); List<Rule> rules = ruleRepository.findAll(predicate);
3. 多条件组合查询
比如要同时满足:
- Rule的name包含"test"
- 存在type为"FOR"的ExpressionGroup,且其中有expression的name是"name3"且values包含"VAL6"
QRule qRule = QRule.rule; Predicate predicate = qRule.name.contains("test") .and(qRule.expressionGroups.any(group -> group.type.eq("FOR") .and(group.expressions.any(expr -> expr.name.eq("name3") .and(expr.values.contains("VAL6")) )) )); List<Rule> rules = ruleRepository.findAll(predicate);
关键注意点
- 针对MongoDB的数组类型,QueryDSL用
any()方法来匹配数组中的任意一个元素满足条件 - 嵌套数组需要逐层用
any()穿透,lambda写法能让复杂嵌套逻辑更易读 - 如果需要匹配数组中的所有元素都满足条件,可以用
all()方法(不过你的场景大概率用any()更多)
内容的提问来源于stack exchange,提问作者user2112716
相关产品推荐
相关产品推荐

