说明
查找前几个阶段中某个字段或表达式的不同值。
语法
distinct 阶段的语法与 select 类似。它接受一个或多个可选择的表达式,用于选择和查找不同的值。当表达式只是一个字段引用时,可以使用字符串:
Node.js
const cities = await db.pipeline()
.collection('/cities')
.distinct("country")
.execute();
const cities = await db.pipeline()
.collection('/cities')
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
客户端示例
Node.js
let cities = await db.pipeline() .collection("cities") .distinct("country") .execute(); cities = await db.pipeline() .collection("cities") .distinct( field("state").toLower().as("normalizedState"), field("country")) .execute();
Web
let cities = await execute(db.pipeline() .collection("cities") .distinct("country")); cities = await execute(db.pipeline() .collection("cities") .distinct( field("state").toLower().as("normalizedState"), field("country")));
Swift
let results = try await db.pipeline() .collection("books") .distinct([ Field("author").toUpper().as("author"), Field("genre") ]) .execute()
Kotlin
var cities = db.pipeline() .collection("cities") .distinct("country") .execute() cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country") ) .execute()
Java
Task<Pipeline.Snapshot> cities; cities = db.pipeline() .collection("cities") .distinct("country") .execute(); cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field cities = client.pipeline().collection("cities").distinct("country").execute() cities = ( client.pipeline() .collection("cities") .distinct(Field.of("state").to_lower().as_("normalizedState"), "country") .execute() )
Java
Pipeline.Snapshot cities1 = firestore.pipeline().collection("cities").distinct("country").execute().get(); Pipeline.Snapshot cities2 = firestore .pipeline() .collection("cities") .distinct(toLower(field("state")).as("normalizedState"), field("country")) .execute() .get();
行为
在投影行为方面,distinct 类似于具有去重的 select,因此 select 可用的任何可选择的表达式也可用于 distinct。
distinct 阶段的工作方式与没有分组的聚合阶段类似。
查找不同的字段值
例如,如需获取以下 cities 集合中每个国家/地区的列表,请执行以下操作:
Node.js
await db.collection('cities').doc('SF').set({name: 'San Francisco', state: 'CA', country: 'USA'});
await db.collection('cities').doc('LA').set({name: 'Los Angeles', state: 'CA', country: 'USA'});
await db.collection('cities').doc('NY').set({name: 'New York', state: 'NY', country: 'USA'});
await db.collection('cities').doc('TOR').set({name: 'Toronto', state: null, country: 'Canada'});
await db.collection('cities').doc('MEX').set({name: 'Mexico City', state: null, country: 'Mexico'});
您可以使用以下方法查找不同的国家/地区:
Node.js
const cities = await db.pipeline()
.collection('/cities')
.distinct("country")
.execute();
这会生成以下结果:
{country: "USA"}
{country: "Canada"}
{country: "Mexico"}
表达式的去重输出
您还可以查找多个字段或更复杂表达式的不同组合。例如:
Node.js
const cities = await db.pipeline()
.collection('/cities')
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
用于获取:
{country: "USA", normalized_state: "ca"}
{country: "USA", normalized_state: "ny"}
{country: "Canada", normalized_state: null}
{country: "Mexico", normalized_state: null}
等效行为
对去重值的等效性判断遵循与等式相同的语义。
这意味着,等效值(例如数学上等效的数值)无论其原始类型(32 位整数、64 位整数、浮点数、十进制数等)如何,都会被视为同一个去重值。
举例来说,在集合 numerics 中,不同的文档分别包含 32 位整数 1、64 位整数 1L 和浮点数 1.0 的 foo 值,distinct 将仅返回 1 个结果。
如果数据集中存在不同的等效值,则相应组的输出值可以是这些等效值中的任意一个。在此示例中,foo 的此值可以作为 1、1L 或 1.0 返回。
即使它看起来是确定性的,您也不应尝试依赖于选择特定值的行为。
内存使用量
distinct 阶段的执行方式取决于可用的索引。如果查询优化器未选择合适的索引,distinct 需要将所有不同的值缓冲到内存中。
如果存在大量不同的值,或者值本身非常大(例如,对巨大的值进行去重),此阶段可能会耗尽内存。
在这种情况下,您应应用过滤条件来限制要执行 distinct 的数据集,或按照建议创建索引,以避免大量使用内存。
查询解释将提供有关实际查询执行计划和分析数据的信息,以帮助进行调试。