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;
}