Spring Data MongoDB 教程

文档计数

在 Spring Data MongoDB 的 3.x 之前版本中,计数操作使用 MongoDB 的内部集合统计信息。随着 MongoDB 事务的引入,这不再可能,因为统计数据无法正确反映需要基于聚合的计数方法的事务期间的潜在变化。因此,在 2.x 版本中,如果没有事务正在执行,则 MongoOperations.count() 将使用集合统计信息。如果有事务正在执行,则 MongoOperations.count() 将使用聚合变量。

从 Spring Data MongoDB 3.x 开始,任何计数操作都会通过 MongoDB 的 countDocuments 使用基于聚合的计数方法,而不考虑过滤条件的存在。如果应用程序可以满足处理收集统计信息的限制,MongoOperations.estimatedCount() 提供了另一种选择。

提示:通过将 MongoTemplate#useEstimatedCount(...) 设置为 true,使用空过滤器查询的 MongoTemplate#count(...) 操作将被委托给 estimatedCount,只要没有活动的事务并且模板没有绑定到会话。通过 MongoTemplate#exactCount() 仍然可以获得准确的数字,但可能会加快速度。

注意:

MongoDB 的本地 countDocuments 方法和 $match 聚合,不支持 $near 和 $nearSphere,但需要 $geoWithin 和 $center 或 $centerSphere,不支持 $minDistance。

因此,一个给定的查询将使用 Reactive-/MongoTemplate 重写计数操作,以绕过这个问题,如下所示。

// 使用 $near 对源查询进行计数
{ location : { $near : [-73.99171, 40.738868], $maxDistance : 1.1 } }

// 现在使用 $geoWithin 和 $center 重写了查询
{ location : { $geoWithin : { $center: [ [-73.99171, 40.738868], 1.1] } } }

// 使用具有 $minDistance 和 $maxDistance 的 $near 对源查询进行计数
{ location : { $near : [-73.99171, 40.738868], $minDistance : 0.1, $maxDistance : 1.1 } }

// 重写的查询现在是 $nor $geowithin 的组合,用于解决不受支持的 $minDistance
{ $and :[
   { $nor :[ { location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868 ], 0.01] } } } ]},
   { location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868 ], 1.1] } } }
] }

在 Spring Data MongoDB 的 MongoTemplate 类中,定了如下几个 count() 方法,用来对文档进行计数,方法定义如下:

  • long count(Query query, Class<?> entityClass) 通过查询给定实体类的集合,返回给定查询的文档数

  • long count(Query query, Class<?> entityClass, String collectionName) 通过使用给定实体类查询给定集合来映射给定查询,返回给定查询的文档数

  • long count(Query query, String collectionName) 返回查询给定集合的给定查询的文档数

示例

下面示例将演示 count 的用法,使用 count 来获取查询文档的个数,代码如下:

package com.hxstrive.springdata.mongodb.count;

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;

/**
* 文档计数
* @author hxstrive.com
*/
@SpringBootTest
public class CountDemo {
   @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").build());
   }


   @Test
   public void count() {
       // Executing count: { "age" : { "$gt" : 25}} in collection: person
       Criteria criteria = Criteria.where("age").gt(25);
       Query query = new Query(criteria);
       long count = mongoTemplate.count(query, Person.class);
       System.out.println("count=" + count);
       // 结果:
       // count=3
   }

   @Test
   public void count2() {
       // Executing count: { "age" : { "$gt" : 25}} in collection: person
       Criteria criteria = Criteria.where("age").gt(25);
       Query query = new Query(criteria);
       long count = mongoTemplate.count(query, mongoTemplate.getCollectionName(Person.class));
       System.out.println("count=" + count);
       // 结果:
       // count=3
   }

   @Test
   public void count3() {
       // Executing count: { "age" : { "$gt" : 25}} in collection: person
       Criteria criteria = Criteria.where("age").gt(25);
       Query query = new Query(criteria);
       long count = mongoTemplate.count(query, Person.class, mongoTemplate.getCollectionName(Person.class));
       System.out.println("count=" + count);
       // 结果:
       // count=3
   }

}

其中,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;
}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号