Counting Documents

模板 API 提供多种方法来计算匹配给定条件的文档数目。其中一个概述如下。

The template API offers various methods to count the number of documents matching a given criteria. One of them outlined below.

template.query(Person.class)
    .matching(query(where("firstname").is("luke")))
    .count();

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

In pre-3.x versions of SpringData MongoDB the count operation used MongoDBs internal collection statistics. With the introduction of MongoDB Transactions this was no longer possible because statistics would not correctly reflect potential changes during a transaction requiring an aggregation-based count approach. So in version 2.x MongoOperations.count() would use the collection statistics if no transaction was in progress, and the aggregation variant if so.

从 Spring Data MongoDB 3.x 开始,任何 count 操作都会使用基于聚合的计数方法通过 MongoDB 的 countDocuments,而不管是否存在筛选条件。如果应用程序对使用集合统计信息有局限性,MongoOperations.estimatedCount() 提供了一个备选方案。

As of Spring Data MongoDB 3.x any count operation uses regardless the existence of filter criteria the aggregation-based count approach via MongoDBs countDocuments. If the application is fine with the limitations of working upon collection statistics MongoOperations.estimatedCount() offers an alternative.

通过将 MongoTemplate#useEstimatedCount(…​) 设置为 trueMongoTemplate#count(…​) 操作(使用空过滤器查询)将委托给 estimatedCount,只要没有活动事务且模板未绑定到 session 即可。通过 MongoTemplate#exactCount 仍然可以获取确切数字,但可以加快速度。

By setting MongoTemplate#useEstimatedCount(…​) to true MongoTemplate#count(…​) operations, that use an empty filter query, will be delegated to estimatedCount, as long as there is no transaction active and the template is not bound to a session. It will still be possible to obtain exact numbers via MongoTemplate#exactCount, but may speed up things.

MongoDB 的本机 countDocuments 方法和 $match 聚合不支持 $near$nearSphere,但需要 $geoWithin 以及 $center$centerSphere,它们都不支持 $minDistance(参见 [role="bare"][role="bare"]https://jira.mongodb.org/browse/SERVER-37043)。

MongoDBs native countDocuments method and the $match aggregation, do not support $near and $nearSphere but require $geoWithin along with $center or $centerSphere which does not support $minDistance (see [role="bare"]https://jira.mongodb.org/browse/SERVER-37043).

因此,给定的 Query 将针对 count 操作使用 Reactive-/MongoTemplate 重新编写,以绕过以下所示问题。

Therefore a given Query will be rewritten for count operations using Reactive-/MongoTemplate to bypass the issue like shown below.

{ location : { $near : [-73.99171, 40.738868], $maxDistance : 1.1 } } 1
{ location : { $geoWithin : { $center: [ [-73.99171, 40.738868], 1.1] } } } 2

{ location : { $near : [-73.99171, 40.738868], $minDistance : 0.1, $maxDistance : 1.1 } } 3
{$and :[ { $nor :[ { location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868 ], 0.01] } } } ]}, { location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868 ], 1.1] } } } ] } 4
1 Count source query using $near.
2 Rewritten query now using $geoWithin with $center.
3 Count source query using $near with $minDistance and $maxDistance.
4 Rewritten query now a combination of $nor $geowithin critierias to work around unsupported $minDistance.