文档菜单
文档首页
/ / /
Kotlin 协程
/ /

聚合构建器

本页内容

  • 概述
  • 匹配
  • 投影
  • 投影计算字段
  • 文档
  • 示例
  • 排序
  • 跳过
  • 限制
  • 查找
  • 左外连接
  • 全连接和未关联子查询
  • 分组
  • 选择-N 累加器
  • MinN
  • MaxN
  • FirstN
  • LastN
  • Top
  • TopN
  • Bottom
  • 底部N
  • 反转
  • 输出
  • 合并
  • 图查找
  • 按计数排序
  • 替换根
  • 添加字段
  • 计数
  • 自动桶
  • 分面
  • 设置窗口字段
  • 加密
  • 填充
  • Atlas全文搜索
  • Atlas搜索元数据
  • Atlas向量搜索

在本指南中,您可以了解如何使用聚合类,该类提供静态工厂方法,用于构建MongoDB Kotlin驱动程序中的聚合管道阶段。

要深入了解聚合,请参阅我们的聚合指南.

本页面的示例假设以下类的导入方法

  • 聚合

  • 过滤器

  • 投影

  • 排序

  • 累积器

import com.mongodb.client.model.Aggregates
import com.mongodb.client.model.Filters
import com.mongodb.client.model.Projections
import com.mongodb.client.model.Sorts
import com.mongodb.client.model.Accumulators

使用这些方法构建管道阶段,并在您的聚合中作为列表指定它们

val matchStage = Aggregates.match(Filters.eq("someField", "someCriteria"))
val sortByCountStage = Aggregates.sortByCount("\$someField")
val results = collection.aggregate(
listOf(matchStage, sortByCountStage)).toList()

本指南中的许多聚合示例都使用了Atlas样本_mflix.movies数据集。此集合中的文档由以下Movie数据类建模,用于与Kotlin驱动程序一起使用

data class Movie(
val title: String,
val year: Int,
val genres: List<String>,
val rated: String,
val plot: String,
val runtime: Int,
val imdb: IMDB
){
data class IMDB(
val rating: Double
)
}

使用 match() 方法创建一个匹配传入文档与指定查询筛选器的 $match 管道阶段,过滤掉不匹配的文档。

提示

筛选器可以是实现 Bson 的任何类的实例,但与使用 筛选器 类结合使用会更方便。

以下示例创建了一个管道阶段,该阶段匹配所有 movies 集合中 title 字段等于 "肖申克的救赎" 的文档。

Aggregates.match(Filters.eq(Movie::title.name, "The Shawshank Redemption"))

使用 project() 方法创建一个 $project 管道阶段来指定文档字段。聚合中的字段投影遵循与查询中的字段投影相同的规则。

提示

尽管投影可以是实现 Bson 的任何类的实例,但与使用 投影 结合使用会更方便。

以下示例创建了一个管道阶段,包含 titleplot 字段,但不包含 _id 字段。

Aggregates.project(
Projections.fields(
Projections.include(Movie::title.name, Movie::plot.name),
Projections.excludeId())
)

《$project》阶段也可以投影计算字段。

以下示例创建了一个管道阶段,将《rated》字段投影到名为《rating》的新字段中,实际上是对字段进行了重命名

Aggregates.project(
Projections.fields(
Projections.computed("rating", "\$${Movie::rated.name}"),
Projections.excludeId()
)
)

使用《documents()`》方法创建一个返回从输入值中获取的文本文档的《$documents》管道阶段。

重要

如果在聚合管道中使用《$documents》阶段,它必须是管道中的第一个阶段。

以下示例创建了一个管道阶段,在《movies》集合中创建具有《title》字段的示例文档

Aggregates.documents(
listOf(
Document(Movie::title.name, "Steel Magnolias"),
Document(Movie::title.name, "Back to the Future"),
Document(Movie::title.name, "Jurassic Park")
)
)

重要

如果您使用《documents()`》方法为聚合管道提供输入,必须在数据库上调用《aggregate()`》方法而不是在集合上。

val docsStage = database.aggregate<Document>( // ... )

使用 sample() 方法创建一个 $sample 管道阶段,从输入中随机选择文档。

以下示例创建了一个管道阶段,从 movies 集合中随机选择5个文档。

Aggregates.sample(5)

使用 sort() 方法创建一个 $sort 管道阶段以按指定标准排序。

提示

虽然排序标准可以是实现 Bson 的任何类的实例,但与使用 排序。

以下示例创建了一个管道阶段,根据 year 字段的值降序排序,然后根据 title 字段的值升序排序。

Aggregates.sort(
Sorts.orderBy(
Sorts.descending(Movie::year.name),
Sorts.ascending(Movie::title.name)
)
)

使用 skip() 方法创建一个 $skip 管道阶段,在将文档传递到下一阶段之前跳过指定数量的文档。

以下示例创建了一个管道阶段,跳过 movies 集合中的前5个文档。

Aggregates.skip(5)

使用$limit 管道阶段来限制传递给下一个阶段的文档数量。

以下示例创建了一个管道阶段,该阶段限制从 movies 集合返回的文档数量为 4

Aggregates.limit(4)

使用 lookup() 方法创建一个 $lookup 管道阶段,以在两个集合之间执行连接和未关联的子查询。

以下示例创建了一个管道阶段,该阶段在样本 mflix 数据库中的 moviescomments 集合之间执行左外连接。

  1. 它将 movies 中的 _id 字段与 comments 中的 movie_id 字段连接起来。

  2. 它将结果输出到 joined_comments 字段。

Aggregates.lookup(
"comments",
"_id",
"movie_id",
"joined_comments"
)

以下示例使用了虚构的 orderswarehouses 集合。数据使用以下 Kotlin 数据类进行建模

data class Order(
@BsonId val id: Int,
val customerId: Int,
val item: String,
val ordered: Int
)
data class Inventory(
@BsonId val id: Int,
val stockItem: String,
val inStock: Int
)

示例创建了一个管道阶段,通过项目以及 inStock 字段中可用的数量是否足以满足 ordered 数量来连接两个集合

val variables = listOf(
Variable("order_item", "\$item"),
Variable("order_qty", "\$ordered")
)
val pipeline = listOf(
Aggregates.match(
Filters.expr(
Document("\$and", listOf(
Document("\$eq", listOf("$\$order_item", "\$${Inventory::stockItem.name}")),
Document("\$gte", listOf("\$${Inventory::inStock.name}", "$\$order_qty"))
))
)
),
Aggregates.project(
Projections.fields(
Projections.exclude(Order::customerId.name, Inventory::stockItem.name),
Projections.excludeId()
)
)
)
val innerJoinLookup =
Aggregates.lookup("warehouses", variables, pipeline, "stockData")

使用 group() 方法创建一个 $group 管道阶段,以按指定表达式对文档进行分组,并为每个不同的分组输出一个文档。

提示

该驱动程序包含具有静态工厂方法的类,这些方法为每个支持的累加器提供。

以下示例创建了一个管道阶段,该阶段按 customerId 字段的值对 orders 集合中的文档进行分组。每个分组将 ordered 字段的值总和和平均值累加到 totalQuantityaverageQuantity 字段中。

Aggregates.group("\$${Order::customerId.name}",
Accumulators.sum("totalQuantity", "\$${Order::ordered.name}"),
Accumulators.avg("averageQuantity", "\$${Order::ordered.name}")
)

有关累加器操作符的更多信息,请参阅服务器手册中的累加器部分。

选择-N 累加器是聚合累加操作符,根据特定的排序返回顶部和底部元素。使用以下构建器之一创建聚合累加操作符

提示

仅当运行 MongoDB v5.2 或更高版本时,才能使用这些选择-N 累加器进行聚合操作。

有关可以使用累加器操作符的聚合管道阶段的信息,请参阅服务器手册中的累加器部分。

选择-N 累加器示例使用 sample-mflix 数据库中的 movies 集合中的文档。

minN()构建器创建返回分组中具有最低n个值的文档数据的$minN累加器。

提示

$minN$bottomN累加器可以执行类似任务。有关每个累加器的推荐用法,请参阅$minN和$bottomN累加器的比较

以下示例演示了如何使用minN()方法返回按year分组的电影中最低三个imdb.rating值。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.minN(
"lowestThreeRatings",
"\$${Movie::imdb.name}.${Movie.IMDB::rating.name}",
3
)
)

有关更多信息,请参阅minN() API文档

maxN()累加器返回分组中具有最高n个值的文档数据。

以下示例演示了如何使用maxN()方法,根据year分组,返回电影中评分最高的两个imdb.rating值。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.maxN(
"highestTwoRatings",
"\$${Movie::imdb.name}.${Movie.IMDB::rating.name}",
2
)
)

有关更多信息,请参阅maxN() API文档

firstN()累加器返回每个分组中按指定排序顺序的前n个文档的数据。

提示

$firstN$topN累加器可以执行类似任务。有关每个累加器的推荐用法,请参阅$firstN和$topN累加器的比较

以下示例演示了如何使用firstN()方法,根据它们进入阶段的顺序,按year分组,返回前两个电影title值。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.firstN(
"firstTwoMovies",
"\$${Movie::title.name}",
2
)
)

有关更多信息,请参阅firstN() API文档

lastN() 累加器返回指定排序顺序下每个分组中最后 n 个文档的数据。

以下示例演示了如何使用 lastN() 方法来显示基于它们进入阶段的顺序,按 year 分组的最后三个电影 title 值。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.lastN(
"lastThreeMovies",
"\$${Movie::title.name}",
3
)
)

有关更多信息,请参阅lastN() API 文档

top() 累加器根据指定的排序顺序返回组中的第一个文档的数据。

以下示例演示了如何使用 top() 方法来返回基于 imdb.rating 的评分最高的电影的前 titleimdb.rating 值,并按 year 分组。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.top(
"topRatedMovie",
Sorts.descending("${Movie::imdb.name}.${Movie.IMDB::rating.name}"),
listOf("\$${Movie::title.name}", "\$${Movie::imdb.name}.${Movie.IMDB::rating.name}")
)
)

请参阅 top() API 文档 获取更多信息。

topN() 累加器返回包含指定字段最高 n 值的文档中的数据。

提示

$firstN$topN累加器可以执行类似任务。有关每个累加器的推荐用法,请参阅$firstN和$topN累加器的比较

以下示例演示了如何使用 topN() 方法根据 runtime 值返回最长三部电影的总时长 titleruntime 值,并按 year 进行分组。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.topN(
"longestThreeMovies",
Sorts.descending(Movie::runtime.name),
listOf("\$${Movie::title.name}", "\$${Movie::runtime.name}"),
3
)
)

请参阅 topN() API 文档 获取更多信息。

累加器 bottom() 返回基于指定排序顺序的组中最后一个文档的数据。

以下示例演示了如何使用 bottom() 方法根据 runtime 值返回最短电影的 titleruntime 值,按 year 分组。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.bottom(
"shortestMovies",
Sorts.descending(Movie::runtime.name),
listOf("\$${Movie::title.name}", "\$${Movie::runtime.name}")
)
)

有关更多信息,请参阅bottom() API 文档

累加器 bottomN() 返回包含指定字段最低 n 值的文档的数据。

提示

$minN$bottomN累加器可以执行类似任务。有关每个累加器的推荐用法,请参阅$minN和$bottomN累加器的比较

以下示例演示了如何使用 bottomN() 方法根据 imdb.rating 值返回评分最低的两部电影的 titleimdb.rating 值,按 year 分组。

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.bottom(
"lowestRatedTwoMovies",
Sorts.descending("${Movie::imdb.name}.${Movie.IMDB::rating.name}"),
listOf("\$${Movie::title.name}", "\$${Movie::imdb.name}.${Movie.IMDB::rating.name}"),
)
)

请参阅bottomN() API 文档获取更多信息。

使用 unwind() 方法创建一个 $unwind 管道阶段,从输入文档中解构数组字段,为每个数组元素创建一个输出文档。

以下示例为 lowestRatedTwoMovies 数组中的每个元素创建一个文档

Aggregates.unwind("\$${"lowestRatedTwoMovies"}")

保留数组字段中缺少或 null 值的文档,或数组为空的文档

Aggregates.unwind(
"\$${"lowestRatedTwoMovies"}",
UnwindOptions().preserveNullAndEmptyArrays(true)
)

包含数组索引(在本例中,在一个名为 "position" 的字段中)

Aggregates.unwind(
"\$${"lowestRatedTwoMovies"}",
UnwindOptions().includeArrayIndex("position")
)

使用 out() 方法创建一个 $out 管道阶段,将所有文档写入同一数据库中指定的集合。

重要

$out 阶段必须是任何聚合管道中的最后一个阶段。

以下示例将管道的结果写入 classic_movies 集合

Aggregates.out("classic_movies")

使用 merge() 方法创建一个 $merge 管道阶段,将所有文档合并到指定的集合中。

重要

$merge 阶段必须是任何聚合管道中的最后一个阶段。

以下示例使用默认选项将管道合并到 nineties_movies 集合

Aggregates.merge("nineties_movies")

以下示例使用一些非默认选项将管道合并到 aggregation 数据库中的 movie_ratings 集合中,如果 yeartitle 都匹配,则替换文档,否则插入文档

Aggregates.merge(
MongoNamespace("aggregation", "movie_ratings"),
MergeOptions().uniqueIdentifier(listOf("year", "title"))
.whenMatched(MergeOptions.WhenMatched.REPLACE)
.whenNotMatched(MergeOptions.WhenNotMatched.INSERT)
)

使用 graphLookup() 方法创建一个 $graphLookup 管道阶段,在指定的集合中执行递归搜索,以将一个文档中指定的字段与另一个文档中指定的字段匹配。

以下示例使用 contacts 集合。数据使用以下 Kotlin 数据类进行建模

data class Users(
val name: String,
val friends: List<String>?,
val hobbies: List<String>?
)

该示例计算《contact》集合中用户的报告图,递归地将《friends》字段中的值与《name》字段进行匹配

Aggregates.graphLookup(
"contacts",
"\$${Users::friends.name}", Users::friends.name, Users::name.name,
"socialNetwork"
)

使用《GraphLookupOptions》,您可以指定递归的深度以及深度字段的名称。在本例中,《$graphLookup》将递归两次,并为每个文档创建一个名为《degrees》的字段,其中包含递归深度信息。

Aggregates.graphLookup(
"contacts",
"\$${Users::friends.name}", Users::friends.name, Users::name.name,
"socialNetwork",
GraphLookupOptions().maxDepth(2).depthField("degrees")
)

使用《GraphLookupOptions》,您可以指定一个过滤器,只有满足该过滤器的文档才会被MongoDB包含在搜索结果中。在本例中,只有《hobbies》字段中包含“golf”的链接会被包含。

Aggregates.graphLookup(
"contacts",
"\$${Users::friends.name}", Users::friends.name, Users::name.name, "socialNetwork",
GraphLookupOptions().maxDepth(1).restrictSearchWithMatch(
Filters.eq(Users::hobbies.name, "golf")
)
)

使用《sortByCount()`》方法创建一个$sortByCount管道阶段,该阶段按给定表达式对文档进行分组,然后按计数降序排序。

提示

《$sortByCount》阶段与一个《$group》阶段和一个带有《$sum》累加器的《$sort》阶段相同。

[
{ "$group": { "_id": <expression to group on>, "count": { "$sum": 1 } } },
{ "$sort": { "count": -1 } }
]

以下示例按《genres》字段对《movies》集合中的文档进行分组,并计算每个不同值的出现次数。

Aggregates.sortByCount("\$${Movie::genres.name}"),

使用《replaceRoot()`》方法创建一个$replaceRoot管道阶段,用指定的文档替换每个输入文档。

以下示例使用一个虚构的 books 集合,其中包含以下 Kotlin 数据类建模的数据

data class Libro(val titulo: String)
data class Book(val title: String, val spanishTranslation: Libro)

每个输入文档都被 spanishTranslation 字段中的嵌套文档所替换

Aggregates.replaceRoot("\$${Book::spanishTranslation.name}")

使用 addFields() 方法创建一个 $addFields 管道阶段,该阶段向文档中添加新字段。

提示

当您不希望对字段包含或排除进行投影时,请使用 $addFields

以下示例将两个新字段 watchedtype 添加到 movie 集合的输入文档中

Aggregates.addFields(
Field("watched", false),
Field("type", "movie")
)

使用 count() 方法创建一个 $count 管道阶段,该阶段计算进入该阶段的文档数量,并将该值分配给指定的字段名称。如果您未指定字段,则 count() 将字段名称默认为 "count"。

提示

$count 阶段是

{ "$group":{ "_id": 0, "count": { "$sum" : 1 } } }

以下示例创建一个管道阶段,该阶段在名为 "total" 的字段中输出传入文档的计数

Aggregates.count("total")

使用 bucket() 方法创建一个 $bucket 管道阶段,该阶段自动根据预定义的边界值对数据进行分桶。

以下示例使用以下 Kotlin 数据类建模的数据

data class Screen(
val id: String,
val screenSize: Int,
val manufacturer: String,
val price: Double
)

此示例创建一个管道阶段,根据文档中 screenSize 字段的值对传入的文档进行分组,包含下限边界,不包括上限边界

Aggregates.bucket("\$${Screen::screenSize.name}", listOf(0, 24, 32, 50, 70, 1000))

使用 BucketOptions 类指定超出指定边界的默认桶,以及指定额外的累加器。

以下示例创建一个管道阶段,根据文档中 screenSize 字段的值对传入的文档进行分组,计算每个桶中文档的数量,将 screenSize 的值推送到名为 matches 的字段中,并将任何大于 "70" 的屏幕尺寸捕获到名为 "monster" 的桶中,用于巨大屏幕尺寸

提示

该驱动程序包含具有静态工厂方法的类,这些方法为每个支持的累加器提供。

Aggregates.bucket("\$${Screen::screenSize.name}", listOf(0, 24, 32, 50, 70),
BucketOptions()
.defaultBucket("monster")
.output(
Accumulators.sum("count", 1),
Accumulators.push("matches", "\$${Screen::screenSize.name}")
)
)

使用 bucketAuto() 方法创建一个 $bucketAuto 管道阶段,该阶段会自动确定每个桶的边界,以便将文档均匀地分布到指定的桶数中。

以下示例使用以下 Kotlin 数据类建模的数据

data class Screen(
val id: String,
val screenSize: Int,
val manufacturer: String,
val price: Double
)

此示例创建一个管道阶段,将尝试使用文档的 price 字段的值创建和均匀地将文档分布在 5 个桶中。

Aggregates.bucketAuto("\$${Screen::screenSize.name}", 5)

使用BucketAutoOptions类来指定一个基于优选数的边界值,并指定额外的累加器。

以下示例创建一个管道阶段,尝试根据文档的price字段值将文档均匀地分配到5个桶中,设置桶边界为2的幂(2,4,8,16,...)。它还统计每个桶中的文档数量,并在名为avgPrice的新字段中计算它们的平均price

提示

该驱动程序包含具有静态工厂方法的类,这些方法为每个支持的累加器提供。

Aggregates.bucketAuto(
"\$${Screen::price.name}", 5,
BucketAutoOptions()
.granularity(BucketGranularity.POWERSOF2)
.output(Accumulators.sum("count", 1), Accumulators.avg("avgPrice", "\$${Screen::price.name}"))
)

使用facet()方法创建一个$facet管道阶段,允许定义并行管道。

以下示例使用以下 Kotlin 数据类建模的数据

data class Screen(
val id: String,
val screenSize: Int,
val manufacturer: String,
val price: Double
)

此示例创建一个管道阶段,执行两个并行聚合

  • 第一个聚合根据文档的screenSize字段将文档分配到5个组中。

  • 第二个聚合统计所有制造商并返回它们的计数,限制为前5个。

Aggregates.facet(
Facet(
"Screen Sizes",
Aggregates.bucketAuto(
"\$${Screen::screenSize.name}",
5,
BucketAutoOptions().output(Accumulators.sum("count", 1))
)
),
Facet(
"Manufacturer",
Aggregates.sortByCount("\$${Screen::manufacturer.name}"),
Aggregates.limit(5)
)
)

使用 setWindowFields() 方法创建一个 $setWindowFields 管道阶段,允许使用窗口操作符在集合中指定的文档范围内执行操作。

提示

窗口函数

驱动程序包括用于构建窗口计算的静态工厂方法的 Windows 类。

以下示例使用一个虚构的 weather 集合,使用以下 Kotlin 数据类进行建模

data class Weather(
val localityId: String,
val measurementDateTime: LocalDateTime,
val rainfall: Double,
val temperature: Double
)

该示例创建了一个管道阶段,计算每个地区的累计降雨量和过去一个月的平均温度,这些数据来自更细粒度的 rainfalltemperature 字段

val pastMonth = Windows.timeRange(-1, MongoTimeUnit.MONTH, Windows.Bound.CURRENT)
val resultsFlow = weatherCollection.aggregate<Document>(
listOf(
Aggregates.setWindowFields("\$${Weather::localityId.name}",
Sorts.ascending(Weather::measurementDateTime.name),
WindowOutputFields.sum(
"monthlyRainfall",
"\$${Weather::rainfall.name}",
pastMonth
),
WindowOutputFields.avg(
"monthlyAvgTemp",
"\$${Weather::temperature.name}",
pastMonth
)
)
)

使用 densify() 方法创建一个 $densify 管道阶段,生成一系列文档以跨越指定的间隔。

提示

您只能在运行 MongoDB v5.1 或更高版本时使用 $densify() 聚合阶段。

考虑以下文档,这些文档来自 Atlas sample weather dataset,包含类似的 position 字段的测量值,每隔一小时测量一次

Document{{ _id=5553a..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:00:00 EST 1984, ... }}
Document{{ _id=5553b..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 09:00:00 EST 1984, ... }}

这些文档使用以下 Kotlin 数据类进行建模

data class Weather(
@BsonId val id: ObjectId = ObjectId(),
val position: Point,
val ts: LocalDateTime
)

假设您需要创建一个管道阶段,该阶段对这些文档执行以下操作

  • 每15分钟添加一个文档,该文档的ts值不存在。

  • position字段对文档进行分组。

执行这些操作的densify()聚合阶段构建器的调用应类似于以下内容

Aggregates.densify(
"ts",
DensifyRange.partitionRangeWithStep(15, MongoTimeUnit.MINUTE),
DensifyOptions.densifyOptions().partitionByFields("Position.coordinates")
)

以下输出突出显示由聚合阶段生成的文档,这些文档在每个现有文档之间每隔15分钟包含一个ts

Document{{ _id=5553a..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:00:00 EST 1984, ... }}
Document{{ position=Document{{coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:15:00 EST 1984 }}
Document{{ position=Document{{coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:30:00 EST 1984 }}
Document{{ position=Document{{coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:45:00 EST 1984 }}
Document{{ _id=5553b..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 09:00:00 EST 1984, ... }}

有关更多信息,请参阅densify包API文档

使用fill()方法创建一个填充null和缺失字段值的$fill管道阶段。

提示

您只能在运行MongoDB v5.3或更高版本时使用$fill()聚合阶段。

考虑以下包含每小时温度和气压测量的文档

Document{{_id=6308a..., hour=1, temperature=23C, air_pressure=29.74}}
Document{{_id=6308b..., hour=2, temperature=23.5C}}
Document{{_id=6308c..., hour=3, temperature=null, air_pressure=29.76}}

这些文档使用以下 Kotlin 数据类进行建模

data class Weather(
@BsonId val id: ObjectId = ObjectId(),
val hour: Int,
val temperature: String?,
val air_pressure: Double?
)

假设您需要按照以下方式在文档中填充缺失的温度和气压数据点

  • 使用线性插值计算值,为小时"2"填充air_pressure字段。

  • 将缺失的temperature值设置为"23.6C"(摄氏度),用于小时"3"。

执行这些操作的fill()聚合阶段构建器的调用类似于以下内容

val resultsFlow = weatherCollection.aggregate<Weather>(
listOf(
Aggregates.fill(
FillOptions.fillOptions().sortBy(Sorts.ascending(Weather::hour.name)),
FillOutputField.value(Weather::temperature.name, "23.6C"),
FillOutputField.linear(Weather::air_pressure.name)
)
)
)
resultsFlow.collect { println(it) }
Weather(id=6308a..., hour=1, temperature=23C, air_pressure=29.74)
Weather(id=6308b..., hour=2, temperature=23.5C, air_pressure=29.75)
Weather(id=6308b..., hour=3, temperature=23.6C, air_pressure=29.76)

请参阅fill包API文档以获取更多信息。

使用search()方法创建一个$search管道阶段,指定对一个或多个字段的全文搜索。

提示

仅适用于MongoDB v4.2及以上版本的Atlas

此聚合管道运算符仅适用于托管在MongoDB Atlas集群上的集合,这些集群运行v4.2或更高版本,并受Atlas搜索索引保护。从Atlas Search文档中了解更多有关所需设置和此运算符的功能信息。

以下示例创建了一个管道阶段,该阶段在movies集合的title字段中搜索包含单词"Future"的文本。

Aggregates.search(
SearchOperator.text(
SearchPath.fieldPath(Movie::title.name), "Future"
),
SearchOptions.searchOptions().index("title")
)

了解有关构建器的更多信息,请参阅搜索包API文档。

使用searchMeta()方法创建一个$searchMeta管道阶段,该阶段仅返回Atlas全文搜索查询的结果元数据部分。

提示

仅在MongoDB v4.4.11及更高版本上的Atlas上可用

此聚合管道运算符仅适用于运行v4.4.11及更高版本的MongoDB Atlas集群。有关版本可用性的详细列表,请参阅MongoDB Atlas文档中的$searchMeta.

以下示例显示了Atlas搜索聚合阶段的count元数据

Aggregates.searchMeta(
SearchOperator.near(1985, 2, SearchPath.fieldPath(Movie::year.name)),
SearchOptions.searchOptions().index("year")
)

了解有关此辅助器的更多信息,请参阅 searchMeta() API 文档。

重要

有关支持此功能的 MongoDB Atlas 版本信息,请参阅 Atlas 文档中的 限制

使用 vectorSearch() 方法创建一个 $vectorSearch 管道阶段,指定一个 语义搜索。语义搜索是一种能够定位意义相似的片段信息的一种搜索类型。

要在集合上执行聚合时使用此功能,您必须创建一个向量搜索索引并索引您的向量嵌入。有关如何在 MongoDB Atlas 中设置搜索索引的说明,请参阅 Atlas 文档中的 如何为向量搜索索引向量嵌入

本节中的示例使用以下 Kotlin 数据类建模的数据

data class MovieAlt(
val title: String,
val year: Int,
val plot: String,
val plotEmbedding: List<Double>
)

本例演示了如何构建一个聚合管道,该管道使用 vectorSearch() 方法执行以下规范的精确向量搜索

  • 使用字符串值的向量嵌入搜索 plotEmbedding 字段值

  • 使用 mflix_movies_embedding_index 向量搜索索引

  • 返回1个文档

  • 筛选年份值至少为2016的文档

Aggregates.vectorSearch(
SearchPath.fieldPath(MovieAlt::plotEmbedding.name),
listOf(-0.0072121937, -0.030757688, -0.012945653),
"mflix_movies_embedding_index",
1.toLong(),
exactVectorSearchOptions().filter(Filters.gte(MovieAlt::year.name, 2016))
)

想了解更多关于此辅助工具的信息,请参阅vectorSearch() API文档。

返回

构建器