MongoDB 提供了一个操作,通过使用该操作可以查询结果中提取单个字段的不同值。结果值不需要具有相同的数据类型,也不限于简单类型。对于检索,实际结果类型对于转换和键入确实很重要。以下示例演示如何查询非重复值:
template.query(Person.class)  ①
  .distinct("lastname")       ②
  .all();                     ③① 查询 Person 集合。
② 选择 lastname 字段的不同值,字段名称根据域类型属性声明进行映射(如果指定了 @Field 注解,则使用注解指定的值)。
③ 检索所有不同的值,作为一个 Object 类型的 List(由于没有明确指定结果类型,见 as() 方法)。
将非重复值检索到对象集合是最灵活的方法,因为它尝试确定域类型的属性值并将结果转换为所需的类型或映射文档结构。
有时,当所需字段的所有值都固定为某种类型时,直接获取正确类型的集合会更方便,如以下示例所示:
template.query(Person.class)  ①
  .distinct("lastname")       ②
  .as(String.class)           ③
  .all();                     ④① 查询 Person 集合。
② 选择 lastname 字段的不同值,字段名称根据域类型属性声明进行映射(如果指定了 @Field 注解,则使用注解指定的值)。
③ 检索到的值被转换为所需的目标类型 —— 这里指定为字符串。如果存储的字段包含的是一个文档,也有可能将值映射到一个更复杂的类型。
④ 检索所有不同的值,作为一个字符串类型的 List<String>。如果该类型不能被转换为所需的目标类型,该方法会抛出一个 DataAccessException。
(1)Person 实体
package com.hxstrive.springdata.mongodb.entity;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.annotation.Version;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* 用户
* @author hxstrive.com
*/
@Document("person")
@TypeAlias("pers")
@Data
@Builder
@ToString
public class Person extends Contact {
   /** ID,自动映射到 MongoDB 的 _id 字段 */
   private String id;
   /** 姓名 */
   private String name;
   /** 年龄 */
   private Integer age;
   /** 版本 */
   @Version
   private Long version;
}(2)客户端代码,如下:
package com.hxstrive.springdata.mongodb.query;
import com.hxstrive.springdata.mongodb.entity.Person;
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 java.util.Arrays;
import java.util.List;
@SpringBootTest
public class QueryDocumentDemo5 {
   @Autowired
   private MongoTemplate mongoTemplate;
   @Test
   public void contextLoads() {
       // 删除集合,清空数据
       mongoTemplate.dropCollection(Person.class);
       // 准备数据
       mongoTemplate.insert(Person.builder().id("1").name("Tom").age(22).build());
       mongoTemplate.insert(Person.builder().id("2").name("Helen").age(29).build());
       mongoTemplate.insert(Person.builder().id("3").name("Bill").age(29).build());
       mongoTemplate.insert(Person.builder().id("4").name("Joe").age(22).build());
       // 查询集合中所有年龄取值
       List<Object> allAgeObj = mongoTemplate.query(Person.class)
               // 获取 age 字段的不重复值
               .distinct("age")
               .all();
       System.out.println(Arrays.toString(allAgeObj.toArray()));
       // 查询集合中所有年龄取值
       List<Integer> allAge = mongoTemplate.query(Person.class)
               // 获取 age 字段的不重复值
               .distinct("age")
               // 将结果映射成 Integer
               .as(Integer.class)
               .all();
       System.out.println(Arrays.toString(allAge.toArray()));
   }
}运行代码,输出结果如下:
[22, 29] [22, 29]
