MongoDB 提供了多个诊断操作符,常用诊断操作符如下:
$expr 操作符允许在查询语句中使用聚合表达式,$expr 可以构建查询表达式,在匹配时,比较同一文档中的字段。例如:
-- 两个字段比较,返回 "sal" 比 "age" 大的文档: db.t_01.find({ $expr: { $gt: ["age","sal"] } })
$jsonSchema 操作符可以被用于文档验证器,用于集合模式验证。例如:
-- 定义一个 users 集合模式验证: db.createCollection("users", { validator: { $jsonSchema: { bsonType: "object", required: ["name", "sex"], properties: { name: { bsonType: "string", description: "must be a string and is required" }, age: { bsonType: "int", description: "must be a integer and is not required" }, sex: { enum: ["male" , "female"], description: "can only be one of the enum values and is required" } } } } ) -- 往集合 users 插入数据 db.users.insert({ "name":"gg", "sex":"male" })
$mod 操作符用来对字段的值执行除以指定值取余数运算。例如:
-- 返回 "age" 字段值被 3 整除的文档 db.t_01.find({ "age" : { $mod : [3,0] } })
$regex 操作符用来选择与指定正则表达式匹配的文档,MongoDB 使用 Perl 兼容正则表达式版本 8.41。例如:
-- 查询 "name" 结尾是 tor 三个字符的文档 db.t_01.find({"name": {$regex : /tor$/ } })
$text 操作符用来对具有文本索引的字段执行文本搜索。例如:
-- 在 t_01 集合的 "name" 上创建 text 索引 db.t_01.createIndex({ "name" : "text"}) -- 使用全文搜索 db.t_01.find({$text: { $search: "david" } } )
$where 操作符用来匹配满足 JavaScript 表达式的文档,使用 $where 操作符将包含 JavaScript 表达式的字符串或完整的 JavaScript 函数传递给查询系统。例如:
-- 查询 "name" 字段为 david 的文档 db.t_01.find({ $where : function() { return (this.name == "david") } })
下面将介绍怎样使用 Criteria 实现诊断查询,Criteria 类定义的诊断查询方法如下:
Criteria andDocumentStructureMatches(MongoJsonSchema schema) 创建一个 Criteria($jsonSchema),根据 MongoJsonSchema 定义的给定结构匹配文档。
Criteria mod(Number value, Number remainder) 使用 $mod 操作符创建一个 Criteria
Criteria regex(String regex) 使用 $regex 操作符创建一个 Criteria
Criteria regex(String regex, String options) 使用 $regex 操作符创建一个 Criteria
下面示例将演示怎样使用 Criteria 的诊断查询方法实现诊断查询,示例如下:
package com.hxstrive.springdata.mongodb; import com.hxstrive.springdata.mongodb.entity.Person; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.schema.JsonSchemaObject; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; import java.util.List; import static org.springframework.data.mongodb.core.schema.JsonSchemaProperty.*; /** * * @author hxstrive.com */ @SpringBootTest class CriteriaDemo4 { @Autowired private MongoTemplate mongoTemplate; @BeforeEach public void init() { // 删除集合 mongoTemplate.dropCollection(Person.class); // 准备数据 mongoTemplate.insert(Person.builder().id(100).name("Tom").age(27).email("Tom@sina.com").build()); mongoTemplate.insert(Person.builder().id(200).name("Helen").age(30).email("Helen@outlook.com").build()); mongoTemplate.insert(Person.builder().id(300).name("Bill").age(47).email("bill@gmail.com").build()); mongoTemplate.insert(Person.builder().id(400).name("Joe").age(20).email("joe@163.com") .summary("User description information").build()); } @Test public void mod() { // 查询文档中 age 字段的值能够被 10 整除 Criteria criteria = Criteria.where("age").mod(10, 0); List<Person> personList = mongoTemplate.query(Person.class) .matching(Query.query(criteria)).all(); for(Person person : personList) { System.out.println(person); } // 结果: // Person(id=200, name=Helen, age=30, email=Helen@outlook.com, summary=null) // Person(id=400, name=Joe, age=20, email=joe@163.com, summary=User description information) } @Test public void regex() { // 查询文档中 name 字段的值由三个大小写字母组成的文档 Criteria criteria = Criteria.where("name").regex("^[a-zA-Z]{3}$"); List<Person> personList = mongoTemplate.query(Person.class) .matching(Query.query(criteria)).all(); for(Person person : personList) { System.out.println(person); } // 结果: // Person(id=100, name=Tom, age=27, email=Tom@sina.com, summary=null) // Person(id=400, name=Joe, age=20, email=joe@163.com, summary=User description information) } @Test public void andDocumentStructureMatches() { /** * { * "type":"object", * "required":["name", "age"], * "properties":{ * "name":{ * "type":"string", * "enum":["Tom","Helen","Bill","Joe"] * }, * "age":{ * "type":"number", * "minimum":20, * "exclusiveMinimum":true, * "maximum":120, * "exclusiveMaximum":true * } * } * } */ MongoJsonSchema schema = MongoJsonSchema.builder() .required("name", "age") .properties( string("name").possibleValues("Tom", "Helen", "Bill", "Joe"), number("age").gt(20).lt(120) ).build(); System.out.println(schema.schemaDocument().toJson()); Criteria criteria = Criteria.where("age").gt(20) .andDocumentStructureMatches(schema); List<Person> personList = mongoTemplate.query(Person.class) .matching(Query.query(criteria)).all(); for(Person person : personList) { System.out.println(person); } // 结果: // Person(id=100, name=Tom, age=27, email=Tom@sina.com, summary=null) // Person(id=200, name=Helen, age=30, email=Helen@outlook.com, summary=null) // Person(id=300, name=Bill, age=47, email=bill@gmail.com, summary=null) } @Test public void andDocumentStructureMatches2() { /** * { * "type":"object", * "required":["name", "age"], * "properties":{ * "name":{ * "type":"string", * "enum":["Tom","Joe"] * }, * "age":{ * "type":"number", * "minimum":40, * "exclusiveMinimum":true, * "maximum":120, * "exclusiveMaximum":true * } * } * } */ MongoJsonSchema schema = MongoJsonSchema.builder() .required("name", "age") .properties( string("name").possibleValues("Tom", "Joe"), number("age").gt(40).lt(120) ).build(); System.out.println(schema.schemaDocument().toJson()); Criteria criteria = Criteria.where("age").gt(20) .andDocumentStructureMatches(schema); List<Person> personList = mongoTemplate.query(Person.class) .matching(Query.query(criteria)).all(); for(Person person : personList) { System.out.println(person); } // 结果: // 没有匹配到任何文档 } }
其中,Person 实体类的代码如下:
package com.hxstrive.springdata.mongodb.entity; import lombok.Builder; import lombok.Data; import lombok.ToString; @Data @ToString @Builder public class Person { /** 用户ID */ private int id; /** 用户姓名 */ private String name; /** 年龄 */ private int age; /** 电子邮件 */ private String email; /** 个人说明 */ private String summary; }