在 MongoDB 中,提供了几个用于数组的操作符,它们分别为 $all、$eleMatch 和 $size 操作符,这些操作符详细描述如下:
$all 操作符用来匹配包含查询中指定的所有元素的数组,例如:
// 查询 t_01 集合的 name 字段同时包含 "deng","groot","lily" 的文档 db.t_01.find( { "name":{ $all: ["deng","groot","lily"] } })
$elemMatch 操作符用来返回数组字段中至少有一个元素与所有指定的元素匹配的文档,例如:
// 查询 students 集合中的 scores 数组字段中,至少有一个大于等于 80 且小于 90 的元素的文档 db.students.find({ scores: { $elemMatch: {$gte:80, $lt: 90} } })
$size 操作符用来返回具有与指定大小一样的数组字段的文档,例如:
// 查询 students 集合中 scores 数组字段中具有 2 个元素的文档 db.students.find({ scores : { $size : 2 } })
下面将介绍怎样使用 Criteria 实现数组查询,Criteria 类定义的数组查询方法如下:
Criteria all(Object... values) 使用 $all 操作符创建一个 Criteria
Criteria all(Collection<?> values) 使用 $all 操作符创建一个 Criteria
Criteria elemMatch(Criteria criteria) 使用 $elemMatch 操作符创建一个 Criteria
Criteria size(int size) 使用 $size 操作符创建一个 Criteria
下面示例将演示怎样使用 Criteria 的数组查询方法实现数组查询,示例如下:
package com.hxstrive.springdata.mongodb; import com.hxstrive.springdata.mongodb.entity.Person; import com.mongodb.client.model.IndexOptions; import org.bson.Document; 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 java.util.Arrays; import java.util.List; /** * 数组查询 * @author hxstrive.com */ @SpringBootTest class CriteriaDemo6 { @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") .interests(new String[]{ "basketball" }) .coordinates(new Double[]{ 116.424966, 39.936625 }) .build()); mongoTemplate.insert(Person.builder().id(200).name("Helen").age(30).email("Helen@outlook.com") .interests(new String[]{ "basketball", "badminton" }) .coordinates(new Double[]{ 114.530044, 38.056057 }) .build()); mongoTemplate.insert(Person.builder().id(300).name("Bill").age(47).email("bill@gmail.com") .interests(new String[]{ "football", "badminton" }) .coordinates(new Double[]{ 114.530044, 38.056057 }) .summary("I am a software engineer and I like Java.") .build()); mongoTemplate.insert(Person.builder().id(400).name("Joe").age(20).email("joe@163.com") .interests(new String[]{ "badminton" }) .coordinates(new Double[]{ 114.364468, 30.650303 }) .summary("I'm a pianist.").build()); // 创建索引 String collectionName = mongoTemplate.getCollectionName(Person.class); mongoTemplate.getCollection(collectionName).createIndex( // 为 coordinates 字段创建 2d 类型的索引 new Document("coordinates", "2d"), // 设置索引名为 idx_coordinates,background 指定索引是否应该在后台创建 new IndexOptions().background(false).name("idx_coordinates")); } @Test public void all() { // 查询文档中有且只有 basketball 和 badminton 兴趣的文档 Criteria criteria = Criteria.where("interests").all("basketball", "badminton"); 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, coordinates=[114.530044, 38.056057], interests=[basketball, badminton]) } @Test public void all2() { // 查询文档中有且只有 basketball 和 badminton 兴趣的文档 List<String> interestList = Arrays.asList("basketball", "badminton"); Criteria criteria = Criteria.where("interests").all(interestList); 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, coordinates=[114.530044, 38.056057], interests=[basketball, badminton]) } @Test public void elemMatch() { // 查询文档中有 basketball 兴趣的文档 Criteria criteria = Criteria.where("interests").elemMatch(new Criteria().in("basketball")); 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, coordinates=[116.424966, 39.936625], interests=[basketball]) // Person(id=200, name=Helen, age=30, email=Helen@outlook.com, summary=null, coordinates=[114.530044, 38.056057], interests=[basketball, badminton]) } @Test public void size() { // 查询文档中只有两种兴趣的文档 Criteria criteria = Criteria.where("interests").size(2); 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, coordinates=[114.530044, 38.056057], interests=[basketball, badminton]) // Person(id=300, name=Bill, age=47, email=bill@gmail.com, summary=I am a software engineer and I like Java., coordinates=[114.530044, 38.056057], interests=[football, badminton]) } }
其中,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; /** 经纬度信息 */ private Double[] coordinates; /** 个人兴趣 */ private String[] interests; }