一.用mongoTemplate 与 Criteria一同使用
MongoTemplate是Spring Data MongoDB中的一个核心类,它提供了一种方式来操作MongoDB数据库。这种操作方式不仅简单易用,而且非常灵活。我们可以通过MongoTemplate来完成大部分的工作,包括创建、更新和删除文档等等。
Criteria
是 Spring Data MongoDB 中的一种查询条件构造器,它用于构建查询条件,以便从 MongoDB 数据库中检索文档。通常,Criteria
被用于查询条件的创建,然后与 Query
对象一起使用,用于执行查询。
- where:
Criteria.where(fieldName)
用于指定要查询的字段名。 - is:
criteria.is(value)
用于指定字段值的精确匹配。 - in:
criteria.in(values)
用于指定字段值在给定值列表中的匹配。 - regex:
criteria.regex(pattern)
用于指定正则表达式匹配。 - ne:
criteria.ne(value)
用于指定字段值不等于给定值的条件。 - lt/le/gt/ge:分别表示小于、小于等于、大于、大于等于。
- exists:
criteria.exists(flag)
用于检查字段是否存在。 - and/or/nor:这些方法用于组合多个条件。
List<Criteria> list = new ArrayList<>();
list.add(Criteria.where("stuId").is(stuId));
list.add(Criteria.where("StuName").regex("^.*" + name + ".*$")); //模糊查询
list.add(Criteria.where("stuId").in(stuIds));
list.add(Criteria.where("stuId").exists("11100")); //查stuId为11100的
// and/or/nor
Criteria criteria = new Criteria().andOperator(
Criteria.where("stuId").is(value1),
Criteria.where("StuName").regex("pattern"),
Criteria.where("age").gt(value2)
);
Query query = new Query(criteria);
List<MyEntity> result = mongoTemplate.find(query, MyEntity.class);
二.复杂结构查询
当你Mongo里的数据结构是复杂结构数组套map的形式
其中dataInfo和studentInfo中的map key都为动态id
dataInfo里为map数据
studentInfo为list 列表数据
{
"_id": ObjectId("653cae5cc13e770843295f30"),
"StudentTypeEntity": DBRef("StudentTypeEntity", ObjectId("653cae5cc13e770843295f23")),
"dataInfo": {
"2a88ec550932ea32c225cbd0dddb29f7": "土木一组",
"8d1f38297c10ea243c871ffda0537650": NumberLong("1633046400000")
},
"studentInfo": [
{
"studentId": "111001",
"studentName": "张三",
"d134fad9307b02e1c625cf42a90fd9b5": NumberInt("1")
},
{
"studentId": "111002",
"studentName": "李四",
"d134fad9307b02e1c625cf42a90fd9b5": NumberInt("2")
}
],
"updateTime": NumberLong("1698475612570"),
"createTime": NumberLong("1698475612570")
}
1.在k-v结构的查找
根据dataInfo的key查给定的值:
list.add(Criteria.where("dataInfo." + key).regex("^.*" + value + ".*$"));
list.add(Criteria.where("dataInfo." + key).is(value));
对应sql:
db.getCollection("StudentEntity").find({ "$and" : [ { "StudentTypeEntity": DBRef("StudentTypeEntity", ObjectId("653cae5cc13e770843295f23")) }, { "dataInfo.2a88ec550932ea32c225cbd0dddb29f7" : { "$regularExpression" : { "pattern" : "^.*土木.*$", "options" : ""}}} ] })
2.在数组结构中查找
根据学号等进行查询:
List<StudentQuery.MapInfo> studentInfo = dataQuery.getStudentInfo();
Criteria[] criteriaArray = new Criteria[studentInfo.size()];
for (int i = 0; i < studentInfo.size(); i++) {
StudentQuery.MapInfo item = studentInfo.get(i);
String key = item.getKey();
String value = item.getValue();
if (item.getIsType() != 0) {
String value1 = "^.*" + value + ".*$";
criteriaArray[i] = Criteria.where("studentInfo").elemMatch(Criteria.where(key).regex(value1));
}else {
// 时间就进行精确查询
criteriaArray[i] = Criteria.where("studentInfo").elemMatch(Criteria.where(key).is(Integer.parseInt(value)));
}
}
对应查询sql:
db.getCollection("StudentEntity").find({ "$and" : [ { "StudentTypeEntity": DBRef("StudentTypeEntity", ObjectId("653cae5cc13e770843295f23")) },
{ "$and" : [{ "studentInfo" : { "$elemMatch" : { "studentId" : { "$regularExpression" : { "pattern" : "^.*20070015.*$", "options" : ""}}}}}]} ] } )
3.在数组中查找多个匹配条件的元素
第一种方法
Criteria.where("studentInfo")
.elemMatch(Criteria.where("studentId").is(studentId)
.and("groups.status").is(true));
这个查询条件的写法使用了elemMatch
来匹配数组中的元素。它会匹配包含指定条件的studentInfo元素。在这里,它会匹配包含studentId等于studentId并且groups里status等于true的元素。
第二种方法
new Criteria().andOperator(
Criteria.where("studentInfo.studentId").is(studentId),
Criteria.where("studentInfo.studentName").is(studentName));
这个查询条件使用andOperator
方法来将多个条件组合在一起,并且直接使用了嵌套的字段路径。由于这两个条件是互相独立的,将会返回同时满足指定条件的元素。它会查找具有以下属性值的文档:
- "studentInfo.studentId" 等于 studentId
- "studentInfo.studentName" 等于 studentName
总结来说,第一种写法使用elemMatch
来匹配数组中的元素,可以更灵活地处理数组元素的条件。而第二种写法则直接指定了嵌套字段的路径,适合于直接比较嵌套字段的数值。
注:如果其中一个匹配元素有多个,用elemMatch会返回匹配的一个元素,而使用andOperator方法会返回多个元素。
另:
在 MongoDB 中,如果在一个数组中有多个元素满足查询条件,find
和 findOne
方法只会返回数组中的第一个匹配的元素,而不是所有匹配的元素。因此,如果你需要返回所有匹配的元素,可以使用 find
方法并遍历结果集,或者使用聚合框架中的 $elemMatch
操作符来实现。
三、单个 Criteria 对象 和 Criteria 数组的区别
criteria = Criteria.where("studentInfo").elemMatch(Criteria.where(key).regex(regexValue));和Criteria[] criteriaArray = new Criteria[studentInfo.size()];的区别
-
单个 Criteria 对象 vs. Criteria 数组:
- 创建一个
Criteria
对象用于每个条件:Criteria
对象表示单个查询条件。在您的情况下,Criteria[] criteriaArray = new Criteria[authorInfo.size()];
创建了一个数组,每个元素都是一个独立的查询条件。 Criteria.where("authorInfo").elemMatch(Criteria.where(key).regex(regexValue))
创建了一个查询条件,这个条件可以包含在数组中或独立使用。
- 创建一个
-
灵活性和维护性:
- 使用
Criteria[]
数组,您可以分别操作每个条件。这种方式更灵活,您可以在条件的级别上进行操作,例如更改或删除单个条件。 - 使用单个
Criteria
对象时,它表示一个完整的查询条件。在某些情况下,这可能更易于维护,因为条件作为单个对象存储和管理。
- 使用
-
适用场景:
- 使用数组适用于需要动态构建条件的情况,因为它允许您根据数据或逻辑条件创建不同数量的条件。
- 使用单个
Criteria
对象适用于已知的、确定的条件。如果您的查询条件在编写代码时已知,并且不太可能在运行时更改,那么使用单个条件可能更直观和清晰。
选择其中一种方法取决于您的具体需求和项目结构。如果需要动态地构建多个查询条件,您可能会选择使用数组。如果条件是固定不变的,您可能更倾向于使用单个条件对象。