Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

$densificar (etapa de agregación)

$densify

Nuevo en la versión 5.1.

Crea nuevos documentos en una secuencia de documentos donde faltan ciertos valores en un campo.

Puede usar $densify a:

  • Rellenar vacíos en datos de series de tiempo.

  • Agregar valores faltantes entre grupos de datos.

  • Complete sus datos con un rango específico de valores.

La etapa $densify tiene esta sintaxis:

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

La etapa $densify toma un documento con estos campos:

Campo
Necesidad
Descripción

Campo

Requerido

El campo para densificar. Los valores de la field especificada deben ser todos valores numéricos o todas fechas.

Los documentos que no contienen el field especificado continúan a través de la pipeline sin modificaciones.

Para especificar un <field> en un documento incrustado o en un arreglo, utiliza notación de puntos.

Para conocer las field restricciones, consulte Restricciones.

Opcional

El conjunto de campos que actúa como clave compuesta para agrupar los documentos. En la $densify etapa, cada grupo de documentos se conoce como una partición.

Si omite este campo, $densify usa una partición para toda la colección.

Para ver un ejemplo, consulte Densificación con particiones.

Para conocer las partitionByFields restricciones, consulte Restricciones.

Requerido

Un objeto que especifica cómo se densifican los datos.

Requerido

Puede especificar range.bounds como:

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

  • Un string: o bien "full" o bien "partition".

Si bounds es una matriz:

  • $densify agrega documentos que abarcan el rango de valores dentro de los límites especificados.

  • El tipo de datos para los límites debe corresponder al tipo de datos del campo que se está densificando.

  • Para detalles sobre el comportamiento, consulta range.bounds Comportamiento.

Si bounds es "full":

  • $densify agrega documentos que abarcan todo el rango de valores del field que se está densificando.

Si bounds es "partition":

  • $densify agrega documentos a cada partición, de forma similar a si hubiera ejecutado una full densificación de rango en cada partición individualmente.

Requerido

La cantidad en la que se incrementará el valor del campo en cada documento. $densify crea un nuevo documento para cada step entre los documentos existentes.

Si se especifica rango.unit, step debe ser un valor entero. De lo contrario, step puede ser cualquier valor numérico.

Obligatorio si el campo es una fecha.

La unidad a aplicar al campo step cuando se incrementan valores de fecha en el campo.

Puedes especificar uno de los siguientes valores para unit como una string:

  • millisecond

  • second

  • minute

  • hour

  • day

  • week

  • month

  • quarter

  • year

Para ver un ejemplo, consulta Densificar datos de series de tiempo.

Para documentos que contengan el campo especificado, $densify produce errores si:

  • Cualquier documento en la colección tiene un valor field de tipo fecha y el campo unit no está especificado.

  • Cualquier documento de la colección tiene un field valor de tipo numérico y se especifica el campo de unidad.

  • El nombre field comienza con $. Tienes que renombrar el campo si deseas densificarlo. Para cambiar el nombre de los campos, usa $project.

  • Novedades de la 8.1 versión: field comparte su prefijo con cualquier campo de la partitionByFields matriz. Por ejemplo, las siguientes combinaciones de field y partitionByFields generan un error:

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

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

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

$densify Errores si algún nombre de campo en el arreglo:

  • Evalúa a un valor que no es una cadena.

  • Comienza con $.

Si range.bounds es un arreglo:

  • El límite inferior indica el valor inicial para los documentos añadidos, independientemente de los documentos que ya estén presentes en la colección.

  • El límite inferior es inclusivo.

  • El límite superior es exclusivo.

  • $densify no filtra los documentos con valores de campo fuera de los límites especificados.

Nota

A partir de MongoDB 8.0, $densify trata los límites con una cota superior e inferior igual como un conjunto vacío y no genera un documento con ese valor para el campo.

En versiones anteriores, $densify trata los límites con un límite inferior y superior iguales como un intervalo cerrado y genera un documento con el valor del límite como valor de campo si la colección aún no contiene un documento con el valor del límite.

Por ejemplo, un rango.bounds de [10, 10] genera un documento extra con el valor de campo 10 en versiones anteriores a 8.0, pero no genera dicho documento en 8.0 ni posteriores.

$densify no garantiza el orden de clasificación de los documentos que produce.

Para garantizar el orden de clasificación, utiliza $sort en el campo por el que quieras clasificar.

Crear una colección de weather que contenga lecturas de temperatura durante intervalos de cuatro horas.

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
}
] )

Este ejemplo utiliza la etapa $densify para completar los intervalos de cuatro horas y lograr una granularidad horaria en los puntos de datos:

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") ]
}
}
}
] )

En el ejemplo:

  • La fase $densify rellena los vacíos de tiempo entre las temperaturas registradas.

    • field: "timestamp" densifica el campo timestamp.

  • range:

    • step: 1 incrementa el campo timestamp en 1 unidad.

    • unit: hour densifica el campo timestamp por hora.

    • bounds: [ ISODate("2021-05-18T00:00:00.000Z"), ISODate("2021-05-18T08:00:00.000Z") ] establece el rango de tiempo que se densifica.

En el siguiente resultado, la etapa $densify llena los espacios de tiempo entre las horas de 00:00:00 y 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
}
]

Crea una colección de coffee que contenga datos de dos variedades de granos de café:

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
}
] )

Este ejemplo utiliza para densificar $densify el altitude campo para cada variety café:

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

La agregación de ejemplo:

  • Divide los documentos por variety para crear un agrupamiento para Arabica Typica y otro para Gesha café.

  • Especifica un full rango, lo que significa que los datos se densifican en todo el rango de documentos existentes para cada partición.

  • Especifica un step de 200, lo que significa que se crean nuevos documentos en intervalos de altitude de 200.

La agregación genera los siguientes documentos:

[
{
_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 }
]

Esta imagen muestra los documentos creados con $densify:

Estado de la colección de café después de la densificación de rango completo
haga clic para ampliar
  • Los cuadrados más oscuros representan los documentos originales de la colección.

  • Los cuadros más claros representan los documentos creados con $densify.

Este ejemplo utiliza solo para densificar los espacios en $densify el altitude campo dentro de variety cada:

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

La agregación de ejemplo:

  • Divide los documentos por variety para crear un agrupamiento para Arabica Typica y otro para Gesha café.

  • Se especifica un rango partition, lo que significa que los datos se densifican dentro de cada partición.

    • Para la partición Arabica Typica, el rango es 600-950.

    • Para la partición Gesha, el rango es 1250-1700.

  • Especifica un step de 200, lo que significa que se crean nuevos documentos en intervalos de altitude de 200.

La agregación genera los siguientes documentos:

[
{
_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
}
]

Esta imagen muestra los documentos creados con $densify:

Estado de la colección de café después de la densificación del rango de partición
haga clic para ampliar
  • Los cuadrados más oscuros representan los documentos originales de la colección.

  • Los cuadros más claros representan los documentos creados con $densify.

Los ejemplos de C# de esta página utilizan la sample_weatherdata.data colección de los conjuntos de datos de ejemplo de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de ejemplo, consulte la sección "Comenzar" en la documentación del controlador MongoDB.NET/C#.

Las siguientes clases Weather y Point modelan los documentos en la colección sample_weatherdata.data:

public class Weather
{
public Guid Id { get; set; }
public Point Position { get; set; }
[BsonElement("ts")]
public DateTime Timestamp { get; set; }
}
public class Point
{
public float[] Coordinates { get; set; }
}

La colección sample_weatherdata.data contiene los siguientes documentos, que incluyen mediciones para el mismo campo position con una diferencia de una hora:

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, ... }}

Para utilizar el driver de MongoDB .NET/C# para añadir una etapa $densify a una pipeline de agregación, llame al Densify()método en un PipelineDefinition objeto.

El siguiente ejemplo crea una etapa de canalización que añade un documento cada 15minutos entre los dos documentos anteriores. El código agrupa estos documentos según los valores de su campo Position.Coordinates.

var densifyTimeRange = new DensifyDateTimeRange(
new DensifyLowerUpperDateTimeBounds(
lowerBound: new DateTime(1984, 3, 5, 8, 0, 0),
upperBound: new DateTime(1984, 3, 5, 9, 0, 0)
),
step: 15,
unit: DensifyDateTimeUnit.Minutes
);
var pipeline = new EmptyPipelineDefinition<Weather>()
.Densify(
field: w => w.Timestamp,
range: densifyTimeRange,
partitionByFields: [w => w.Position.Coordinates]);

La etapa de agregación anterior genera los siguientes documentos destacados en la colección:

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, ... }}

Los ejemplos de Node.js en esta página utilizan la colección sample_weatherdata.data de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, se puede consultar Primeros pasos en la documentación del driver de MongoDB Node.js.

La colección sample_weatherdata.data contiene los siguientes documentos, que incluyen mediciones para el mismo campo position con una diferencia de una hora:

{_id: new ObjectId(...), ts: 1984-03-05T13:00:00.000Z, position: {type: 'Point', coordinates: [-47.9, 47.6]}, ... },
{_id: new ObjectId(...), ts: 1984-03-05T14:00:00.000Z, position: {type: 'Point', coordinates: [-47.9, 47.6]}, ... }

Para utilizar el controlador de MongoDB Node.js para agregar una etapa de $densify a una canalización de agregación, utilice el Operador $densify en un objeto de canalización.

El siguiente ejemplo crea una etapa de pipeline que añade un documento cada intervalo de 15minutos entre los dos documentos anteriores. A continuación, el código agrupa estos documentos según los valores de su campo position.coordinates. Luego, el ejemplo ejecuta la pipeline de agregación:

const pipeline = [
{
$densify: {
field: "ts",
partitionByFields: ["position.coordinates"],
range: {
step: 15,
unit: "minute",
bounds: [new Date(1984, 3, 5, 8, 0, 0), new Date(1984, 3, 5, 9, 0, 0)]
}
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

La etapa de agregación anterior genera los siguientes documentos destacados en la colección:

{ _id: new ObjectId(...), ts: 1984-03-05T13:00:00.000Z, position: {type: 'Point', coordinates: [-47.9, 47.6]}, ... },
{ position: { coordinates: [-47.9, 47.6] }, ts: 1984-03-05T13:15:00.000Z },
{ position: { coordinates: [-47.9, 47.6] }, ts: 1984-03-05T13:30:00.000Z },
{ position: { coordinates: [-47.9, 47.6] }, ts: 1984-03-05T13:45:00.000Z },
{ _id: new ObjectId(...), ts: 1984-03-05T14:00:00.000Z, position: {type: 'Point', coordinates: [-47.9, 47.6]}, ... }

Volver

$currentOp

En esta página