定义
The $lookup stage performs a left outer join of the stream of messages from your $source to an Atlas collection in your Connection Registry.
根据您的使用案例,$lookup 管道阶段将使用以下三种语法之一:
要了解更多信息,请参阅$lookup 语法。
警告
使用 $lookup 扩充流可能会降低流处理速度。
以下原型表单展示了所有可用字段:
{ "$lookup": { "from": { "connectionName": "<registered-atlas-connection>", "db": "<registered-database-name>", "coll": "<atlas-collection-name>", "readPreference": "<read-preference>", "readPreferenceTags": [ {"<key>": "<value>"}, ... ] }, "localField": "<field-in-source-messages>", "foreignField": "<field-in-from-collection>", "let": { <var_1>: <expression>, <var_2>: <expression>, …, <var_n>: <expression> }, "pipeline": [ <pipeline to run> ], "as": "<output-array-field>", "parallelism": <integer>, "partitionBy": <expression> } }
语法
$lookup 阶段采用包含以下字段的文档:
字段 | 类型 | 必要性 | 说明 |
|---|---|---|---|
from | 文档 | 可选的 | 用于指定Atlas数据库中要加入到来自 如果指定此字段,则必须指定此文档中所有字段的值。 如果您指定 |
from.connectionName | 字符串 | 可选的 | 连接注册表中的连接名称。 如果您指定 |
from.db | 字符串 | 可选的 | 包含您要加入的集合的 Atlas 数据库名称。 如果您指定 |
from.coll | 字符串 | 可选的 | 您想要加入的集合的名称。 如果您指定 |
from.readPreference | 字符串 | Optional | Read preference for 默认值为 |
from.readPreferenceTags | 阵列 | Optional | Read preference tags for |
localField | 字符串 | 可选的 | |
foreignField | 字符串 | 可选的 | |
let | 文档 | 可选的 | |
管道 | 文档 | 可选的 | |
作为 | 字符串 | 必需 | 要添加到输入文档中的新数组字段的名称。这个新数组字段包含 |
| 整型 | Optional | 向 必须是介于 每个流处理器都有一个由其层级确定的最大累积并行度值。流处理器的累积并行度计算如下:
示例,如果您的 如果流处理器超过其层级的最大累积并行度, Atlas Stream Processing会引发错误,并建议您实现预期并行度层级所需的最低处理器层级。您必须将处理器扩展到更高层级,或降低阶段的并行度值,才能解决该错误。要学习,了解更多信息,请参阅Stream Processing。 |
| 表达式(expression) | Optional | 用于将输入流划分为并行线程的表达式。Atlas Stream Processing将具有相同 如果未指定此字段,则输入文档将通过循环发送到并行线程。 |
行为
The Atlas Stream Processing version of $lookup performs a left outer join of messages from your $source and the documents in a specified Atlas collection. This version behaves similarly to the $lookup stage available in a standard MongoDB database. However, this version requires that you specify an Atlas collection from your Connection Registry as the value for the from field.
The pipeline can contain a nested $lookup stage. If you include a nested $lookup stage in your pipeline, you must use the standard from syntax to specify a collection in the same remote Atlas connection as the outer $lookup stage.
例子
$lookup : { from: {connectionName: "dbsrv1", db: "db1", coll: "coll1"}, …, pipeline: [ …, { $lookup: { from: "coll2", …, } }, …, ] }
If your pipeline has both $lookup and $merge on the same collection, Atlas Stream Processing results might vary if you try to maintain an incremental view. Atlas Stream Processing processes multiple source messages simultaneously and then merges them all together. If multiple messages have the same ID, which both $lookup and $merge use, Atlas Stream Processing might return results that haven't yet materialized.
例子
考虑以下输入流:
{ _id: 1, count: 2 } { _id: 1, count: 3 }
假设查询包含管道内的以下内容:
{ ..., pipeline: [ { $lookup on _id == foreignDoc._id from collection A } { $project: { _id: 1, count: $count + $foreignDoc.count } } { $merge: { into collection A } } ] }
如果尝试保持增量视图,则可能会看到类似于以下内容的结果:
{ _id: 1, count: 5 }
但是,Atlas Stream Processing 可能会返回 5 或 3 的计数,具体取决于 Atlas Stream Processing 是否处理了文档。
For more information, see $lookup.
示例
A streaming data source generates detailed weather reports from various locations, conformant to the schema of the Sample Weather Dataset. A collection named humidity_descriptions contains documents of the form:
其中,relative_humidity 字段描述了室温( 20 摄氏度)下的相对湿度, condition列出了适合该湿度水平的语言描述符。您可以使用 $lookup 阶段,用推荐的描述符来丰富流媒体天气报告,方便气象学家在天气预报广播中使用。
以下聚合有四个阶段:
The
$sourcestage establishes a connection with the Apache Kafka broker collecting these reports in a topic namedmy_weatherdata, exposing each record as it is ingested to the subsequent aggregation stages. This stage also overrides the name of the timestamp field it projects, setting it toingestionTime.$lookup阶段将humidity_descriptions数据库中的记录合并到dewPoint字段的天气报告中。The
$matchstage excludes documents that have an emptyhumidity_infofield, and passes along documents with a populatedhumidity_infofield to the next stage.The
$mergestage writes the output to an Atlas collection namedenriched_streamin thesample_weatherstreamdatabase. If no such database or collection exist, Atlas creates them.
{ '$source': { connectionName: 'sample_weatherdata', topic: 'my_weatherdata', tsFieldName: 'ingestionTime' } }, { '$lookup': { from: { connectionName: 'weatherStream', db: 'humidity', coll: 'humidity_descriptions' }, 'localField':'dewPoint.value', 'foreignField':'dewPoint', 'as': 'humidity_info' } } { '$match': { 'humidity_info': { '$ne': [] } } } { '$merge': { into: { connectionName: 'weatherStream', db: 'sample_weatherstream', coll: 'enriched_stream' } } }
要查看生成的 sample_weatherstream.enriched_stream 集合中的文档,请连接到您的 Atlas 集群并运行以下命令:
db.getSiblingDB("sample_weatherstream").enriched_stream.find()
{ st: 'x+55100+006100', position: { type: 'Point', coordinates: [ 92.7, -53.6 ] }, elevation: 9999, callLetters: 'UECN', qualityControlProcess: 'V020', dataSource: '4', type: 'FM-13', airTemperature: { value: -11, quality: '9' }, dewPoint: { value: 12.5, quality: '1' }, pressure: { value: 1032.7, quality: '9' }, wind: { direction: { angle: 300, quality: '9' }, type: '9', speed: { rate: 23.6, quality: '2' } }, visibility: { distance: { value: 14000, quality: '1' }, variability: { value: 'N', quality: '1' } }, skyCondition: { ceilingHeight: { value: 390, quality: '9', determination: 'C' }, cavok: 'N' }, sections: [ 'SA1', 'AA1', 'OA1', 'AY1', 'AG1' ], precipitationEstimatedObservation: { discrepancy: '4', estimatedWaterDepth: 21 }, atmosphericPressureChange: { tendency: { code: '1', quality: '1' }, quantity3Hours: { value: 5.5, quality: '1' }, quantity24Hours: { value: 99.9, quality: '9' } }, seaSurfaceTemperature: { value: 1.3, quality: '9' }, waveMeasurement: { method: 'M', waves: { period: 4, height: 2.5, quality: '9' }, seaState: { code: '00', quality: '9' } }, pastWeatherObservationManual: { atmosphericCondition: { value: '4', quality: '1' }, period: { value: 6, quality: '1' } }, skyConditionObservation: { totalCoverage: { value: '07', opaque: '99', quality: '1' }, lowestCloudCoverage: { value: '06', quality: '1' }, lowCloudGenus: { value: '07', quality: '9' }, lowestCloudBaseHeight: { value: 2250, quality: '9' }, midCloudGenus: { value: '07', quality: '9' }, highCloudGenus: { value: '00', quality: '1' } }, presentWeatherObservationManual: { condition: '75', quality: '1' }, atmosphericPressureObservation: { altimeterSetting: { value: 9999.9, quality: '9' }, stationPressure: { value: 1032.6, quality: '1' } }, skyCoverLayer: { coverage: { value: '09', quality: '1' }, baseHeight: { value: 240, quality: '9' }, cloudType: { value: '99', quality: '9' } }, liquidPrecipitation: { period: 6, depth: 3670, condition: '9', quality: '9' }, extremeAirTemperature: { period: 99.9, code: 'N', value: -30.9, quantity: '9' }, ingestionTime: ISODate('2024-09-19T20:04:34.346Z'), humidity_info: [ { _id: ObjectId('66ec805ad3cfbba767ebf7a5'), dewPoint: 12.5, relativeHumidity: 62, condition: 'humid, muggy' } ], }
注意
以上是一个有代表性的示例。流数据不是静态的,每个用户看到的都是不同的文档。