Distinct(转换阶段)
说明
查找一系列表达式的所有不同值组合。
distinct(...) 阶段的语法与 select(...) 类似,因为它接受一个或
多个可选择的表达式。当表达式只是一个字段引用时,可以使用字符串:
示例
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
Android
var cities = db.pipeline() .collection("cities") .distinct("country") .execute() cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country") ) .execute()
Java
Android
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(...) 阶段的工作方式与没有组的
aggregate(...) 阶段类似。另请参阅
aggregate(...) 和
select(...)。
查找不同的字段值
例如,如需获取以下 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 中,不同的文档分别包含
foo 值为 32 位整数 1、64 位整数 1L 和浮点数 1.0
,distinct(...) 将仅返回 1 个结果。
如果数据集中存在不同的等效值,则相应组的输出值可以是这些等效值中的任意一个 。
在此示例中,foo 的此值可以作为 1、1L 或 1.0 返回。
即使它看起来是确定性的,您也不应尝试依赖于选择特定值的行为。
内存使用量
distinct(...) 阶段的执行方式取决于可用的索引。如果查询优化器未选择合适的索引,distinct(...) 需要将所有不同的值缓冲到内存中。
如果存在大量不同的值,或者值本身非常大(例如,对巨大的值进行去重),此阶段可能会耗尽内存。
在这种情况下,您应应用过滤条件来限制要执行 distinct(...) 的数据集,或按照建议创建索引,以避免大量使用内存。
查询解释将提供有关实际查询执行计划和分析数据的信息,以帮助进行调试。