对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Docs 菜单

$densify(聚合阶段)

$densify

5.1版本新增。

在文档序列中创建新文档,其中缺少字段中的某些值。

You can use $densify to:

  • 填补时间序列数据的空白

  • 在数据群组之间添加缺失值。

  • 用指定的数值范围填充数据。

The $densify stage has this syntax:

{
$densify: {
field: <fieldName>,
partitionByFields: [ <field 1>, <field 2> ... <field n> ],
range: {
step: <number>,
unit: <time unit>,
bounds: < "full" || "partition" > || [ < lower bound >, < upper bound > ]
}
}
}

The $densify stage takes a document with these fields:

字段
必要性
说明

必需

要密集化的字段。指定 field 的值必须全部为数值或全部为日期。

不包含指定的 field 的文档将继续通过管道而不作修改。

要在嵌入式文档或数组中指定 <field>,请使用点符号。

For restrictions, see field Restrictions.

Optional

The set of fields to act as the compound key to group the documents. In the $densify stage, each group of documents is known as a partition.

If you omit this field, $densify uses one partition for the entire collection.

For an example, see Densification with Partitions.

For restrictions, see partitionByFields Restrictions.

必需

指定如何密集化数据的对象。

必需

您可以将 range.bounds 指定为其中之一:

  • An array: [ < lower bound >, < upper bound > ],

  • 字符串:"full" 或 "partition"。

如果 bounds 是数组:

  • $densify 添加跨越指定边界内的取值范围的文档。

  • The data type for the bounds must correspond to the data type in the field being densified.

  • For behavior details, see range.bounds Behavior.

如果 bounds 为 "full":

  • $densify adds documents spanning the full range of values of the field being densified.

如果 bounds 为 "partition":

  • $densify adds documents to each partition, similar to if you had run a full range densification on each partition individually.

必需

The amount to increment the field value in each document. $densify creates a new document for each step between the existing documents.

If range.unit is specified, step must be an integer. Otherwise, step can be any numeric value.

如果字段是日期,则为必填项。

The unit to apply to the step field when incrementing date values in field.

您可以将 unit 的以下值之一指定为字符串:

  • millisecond

  • second

  • minute

  • hour

  • day

  • week

  • month

  • quarter

  • year

有关示例,请参阅密集化时间序列数据。

For documents that contain the specified field, $densify errors if:

  • Any document in the collection has a field value of type date and the unit field is not specified.

  • 集合中的任何文档都有数值类型的 field 值,并指定了单位字段。

  • field 名称以 $ 开头。如果要密集化字段,必须重新命名。如需重命名字段,请使用 $project。

  • 8.1 版本中的新增功能:

    field 与 partitionByFields 数组中的任何字段共享其前缀。例如,示例的以下组合field 和 partitionByFields 会导致错误:

    • field: "timestamp", partitionByFields: ["timestamp"]

    • field: "timestamp", partitionByFields: ["timestamp.hours"]

    • field: "timestamp.hours", partitionByFields: ["timestamp"]

$densify errors if any field name in the partitionByFields array:

  • 求值为非字符串值。

  • 以 $ 开头。

如果 range.bounds 是一个数组:

  • 下限值表示新增文档的起始值,与集合中已有的文档无关。

  • 下限包含在内。

  • 不含上边界。

  • $densify does not filter out documents with field values outside of the specified bounds.

注意

Starting in MongoDB 8.0, $densify treats bounds with an equal lower and upper bound as an empty set and does not generate a document with the bound as the field value.

In prior versions, $densify treats bounds with an equal lower and upper bound as a closed interval and generates a document with the bound value as a field value if the collection does not already contain a document with the bound value.

For example, a range.bounds of [10, 10] generates an extra document with field value 10 in versions prior to 8.0, but does not generate such a document in 8.0 and later.

$densify returns an error if it generates more documents than the limit set by the internalQueryMaxAllowedDensifyDocs parameter. By default, this limit is 500,000 documents.

要允许生成更多的文档,请增加 internalQueryMaxAllowedDensifyDocs 参数的值。

$densify 不保证其输出的文档的排序顺序。

如需保证排序顺序,请在要排序的字段上使用 $sort。

创建 weather 集合,其中包含每隔四小时的温度读数。

db.weather.insertMany( [
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
"temp": 12
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T04:00:00.000Z"),
"temp": 11
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T08:00:00.000Z"),
"temp": 11
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T12:00:00.000Z"),
"temp": 12
}
] )

This example uses the $densify stage to fill in the gaps between the four-hour intervals to achieve hourly granularity for the data points:

db.weather.aggregate( [
{
$densify: {
field: "timestamp",
range: {
step: 1,
unit: "hour",
bounds:[ ISODate("2021-05-18T00:00:00.000Z"), ISODate("2021-05-18T08:00:00.000Z") ]
}
}
}
] )

在示例中:

  • The $densify stage fills in the gaps of time in between the recorded temperatures.

    • field: "timestamp" 密集化 timestamp 字段。
  • range:

    • step: 1 将 timestamp 字段增加 1 个单位。

    • unit: hour 按小时密集化 timestamp 字段。

    • bounds: [ ISODate("2021-05-18T00:00:00.000Z"), ISODate("2021-05-18T08:00:00.000Z") ] 设置密集化的时间范围。

In the following output, the $densify stage fills in the gaps of time between the hours of 00:00:00 and 08:00:00.

[
{
_id: ObjectId("618c207c63056cfad0ca4309"),
metadata: { sensorId: 5578, type: 'temperature' },
timestamp: ISODate("2021-05-18T00:00:00.000Z"),
temp: 12
},
{ timestamp: ISODate("2021-05-18T01:00:00.000Z") },
{ timestamp: ISODate("2021-05-18T02:00:00.000Z") },
{ timestamp: ISODate("2021-05-18T03:00:00.000Z") },
{
_id: ObjectId("618c207c63056cfad0ca430a"),
metadata: { sensorId: 5578, type: 'temperature' },
timestamp: ISODate("2021-05-18T04:00:00.000Z"),
temp: 11
},
{ timestamp: ISODate("2021-05-18T05:00:00.000Z") },
{ timestamp: ISODate("2021-05-18T06:00:00.000Z") },
{ timestamp: ISODate("2021-05-18T07:00:00.000Z") },
{
_id: ObjectId("618c207c63056cfad0ca430b"),
metadata: { sensorId: 5578, type: 'temperature' },
timestamp: ISODate("2021-05-18T08:00:00.000Z"),
temp: 11
}
{
_id: ObjectId("618c207c63056cfad0ca430c"),
metadata: { sensorId: 5578, type: 'temperature' },
timestamp: ISODate("2021-05-18T12:00:00.000Z"),
temp: 12
}
]

创建 coffee 集合,其中包含两种咖啡豆的数据:

db.coffee.insertMany( [
{
"altitude": 600,
"variety": "Arabica Typica",
"score": 68.3
},
{
"altitude": 750,
"variety": "Arabica Typica",
"score": 69.5
},
{
"altitude": 950,
"variety": "Arabica Typica",
"score": 70.5
},
{
"altitude": 1250,
"variety": "Gesha",
"score": 88.15
},
{
"altitude": 1700,
"variety": "Gesha",
"score": 95.5,
"price": 1029
}
] )

This example uses $densify to densify the altitude field for each coffee variety:

db.coffee.aggregate( [
{
$densify: {
field: "altitude",
partitionByFields: [ "variety" ],
range: {
bounds: "full",
step: 200
}
}
}
] )

聚合示例:

  • 按 variety 对文档分区,为 Arabica Typica 和 Gesha 咖啡分别创建一个分组。

  • 指定 full 范围,这意味着数据在每个分区的整个现有文档范围内进行密集化。

  • 指定 step 为 200,意味着以 200 的 altitude 间隔创建新文档。

该聚合输出以下文档:

[
{
_id: ObjectId("618c031814fbe03334480475"),
altitude: 600,
variety: 'Arabica Typica',
score: 68.3
},
{
_id: ObjectId("618c031814fbe03334480476"),
altitude: 750,
variety: 'Arabica Typica',
score: 69.5
},
{ variety: 'Arabica Typica', altitude: 800 },
{
_id: ObjectId("618c031814fbe03334480477"),
altitude: 950,
variety: 'Arabica Typica',
score: 70.5
},
{ variety: 'Gesha', altitude: 600 },
{ variety: 'Gesha', altitude: 800 },
{ variety: 'Gesha', altitude: 1000 },
{ variety: 'Gesha', altitude: 1200 },
{
_id: ObjectId("618c031814fbe03334480478"),
altitude: 1250,
variety: 'Gesha',
score: 88.15
},
{ variety: 'Gesha', altitude: 1400 },
{ variety: 'Gesha', altitude: 1600 },
{
_id: ObjectId("618c031814fbe03334480479"),
altitude: 1700,
variety: 'Gesha',
score: 95.5,
price: 1029
},
{ variety: 'Arabica Typica', altitude: 1000 },
{ variety: 'Arabica Typica', altitude: 1200 },
{ variety: 'Arabica Typica', altitude: 1400 },
{ variety: 'Arabica Typica', altitude: 1600 }
]

This image visualizes the documents created with $densify:

全范围密集化后咖啡集合的状态
点击放大
  • 较深的方块表示集合中的原始文档。

  • The lighter squares represent the documents created with $densify.

This example uses $densify to only densify gaps in the altitude field within each variety:

db.coffee.aggregate( [
{
$densify: {
field: "altitude",
partitionByFields: [ "variety" ],
range: {
bounds: "partition",
step: 200
}
}
}
] )

聚合示例:

  • 按 variety 对文档分区,为 Arabica Typica 和 Gesha 咖啡分别创建一个分组。

  • 指定 partition 范围,这意味着数据在每个分区内均已加密。

    • 对于 Arabica Typica 分区,范围是 600-950。

    • 对于 Gesha 分区,范围是 1250-1700。

  • 指定 step 为 200,意味着以 200 的 altitude 间隔创建新文档。

该聚合输出以下文档:

[
{
_id: ObjectId("618c031814fbe03334480475"),
altitude: 600,
variety: 'Arabica Typica',
score: 68.3
},
{
_id: ObjectId("618c031814fbe03334480476"),
altitude: 750,
variety: 'Arabica Typica',
score: 69.5
},
{ variety: 'Arabica Typica', altitude: 800 },
{
_id: ObjectId("618c031814fbe03334480477"),
altitude: 950,
variety: 'Arabica Typica',
score: 70.5
},
{
_id: ObjectId("618c031814fbe03334480478"),
altitude: 1250,
variety: 'Gesha',
score: 88.15
},
{ variety: 'Gesha', altitude: 1450 },
{ variety: 'Gesha', altitude: 1650 },
{
_id: ObjectId("618c031814fbe03334480479"),
altitude: 1700,
variety: 'Gesha',
score: 95.5,
price: 1029
}
]

This image visualizes the documents created with $densify:

分区范围密集化后的咖啡集合状况
点击放大
  • 较深的方块表示集合中的原始文档。

  • The lighter squares represent the documents created with $densify.

给本页内容打分