sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB $round vs $trunc:¿Cuál es la diferencia?

El marco de canalización de agregación de MongoDB incluye un $round operador y un $trunc operador. Estos operadores realizan tareas similares, pero diferentes.

Definiciones

Primero, veamos las definiciones de cada operador:

  • La $round operador rondas un número a un entero entero o a un lugar decimal especificado.
  • El $truncate el operador trunca un número a un entero entero o a un lugar decimal especificado.

Básicamente, la diferencia está en las palabras redonda vs truncar .

En algunos casos, ambos operadores devolverán el mismo resultado. En otros casos, sus resultados serán diferentes. Esto se debe a que $round el operador puede redondear el número, dependiendo del valor. El $truncate el operador no redondea el número. En cambio, simplemente lo trunca. En otras palabras, simplemente corta el número como se especifica, mientras deja los dígitos restantes como están.

Ejemplo

Supongamos que tenemos una colección llamada test con los siguientes documentos:

{ "_id" : 1, "data" : 8.99 }
{ "_id" : 2, "data" : 8.45 }
{ "_id" : 3, "data" : 8.451 }
{ "_id" : 4, "data" : -8.99 }
{ "_id" : 5, "data" : -8.45 }
{ "_id" : 6, "data" : -8.451 }
{ "_id" : 7, "data" : 8 }
{ "_id" : 8, "data" : 0 }
{ "_id" : 9, "data" : 0.5 }
{ "_id" : 10, "data" : 8111.32 }
{ "_id" : 11, "data" : 8514.321 }
{ "_id" : 12, "data" : 8999.454 }

Esto es lo que sucede cuando aplicamos $round y $truncate a esos documentos:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data" ] },
            truncated: { $trunc: [ "$data" ] }
          }
     }
   ]
)

Resultado:

{ "data" : 0, "rounded" : 0, "truncated" : 0 }
{ "data" : 8, "rounded" : 8, "truncated" : 8 }
{ "data" : 0.5, "rounded" : 0, "truncated" : 0 }
{ "data" : 0.9, "rounded" : 1, "truncated" : 0 }
{ "data" : 8.99, "rounded" : 9, "truncated" : 8 }
{ "data" : 8.45, "rounded" : 8, "truncated" : 8 }
{ "data" : 8.451, "rounded" : 8, "truncated" : 8 }
{ "data" : -8.99, "rounded" : -9, "truncated" : -8 }
{ "data" : -8.45, "rounded" : -8, "truncated" : -8 }
{ "data" : -8.451, "rounded" : -8, "truncated" : -8 }

Podemos ver que en algunos casos, el resultado es el mismo. En otros, es diferente. Por ejemplo, cuando el valor de entrada es 0.9 , el $round el operador redondea el número a 1 . El $truncate por otro lado, el operador simplemente elimina el .9 part, que produce un resultado de 0 .

Lugares fraccionarios negativos

Ambos operadores aceptan un segundo argumento opcional. Cuando está presente, este argumento especifica el número de lugares decimales para redondear/truncar el número.

Proporcionar este segundo argumento puede resaltar aún más la diferencia entre los dos operadores.

Ejemplo:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data", 1 ] },
            truncated: { $trunc: [ "$data", 1 ] }
          }
     }
   ]
)

Resultado:

{ "data" : 0, "rounded" : 0, "truncated" : 0 }
{ "data" : 8, "rounded" : 8, "truncated" : 8 }
{ "data" : 0.5, "rounded" : 0.5, "truncated" : 0.5 }
{ "data" : 0.9, "rounded" : 0.9, "truncated" : 0.9 }
{ "data" : 8.99, "rounded" : 9, "truncated" : 8.9 }
{ "data" : 8.45, "rounded" : 8.4, "truncated" : 8.4 }
{ "data" : 8.451, "rounded" : 8.5, "truncated" : 8.4 }
{ "data" : -8.99, "rounded" : -9, "truncated" : -8.9 }
{ "data" : -8.45, "rounded" : -8.4, "truncated" : -8.4 }
{ "data" : -8.451, "rounded" : -8.5, "truncated" : -8.4 }

Nuevamente podemos ver que algunos resultados son idénticos mientras que otros no lo son.

Lugares fraccionarios negativos

Ambos operadores aceptan un valor negativo para el segundo argumento.

Ejemplo:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            data: 1,
            rounded: { $round: [ "$data", -1 ] },
            truncated: { $trunc: [ "$data", -1 ] }
          }
     }
   ]
)

Resultado:

{ "data" : 0, "rounded" : 0, "truncated" : 0 }
{ "data" : 8, "rounded" : 10, "truncated" : 0 }
{ "data" : 0.5, "rounded" : 0, "truncated" : 0 }
{ "data" : 0.9, "rounded" : 0, "truncated" : 0 }
{ "data" : 8.99, "rounded" : 10, "truncated" : 0 }
{ "data" : 8.45, "rounded" : 10, "truncated" : 0 }
{ "data" : 8.451, "rounded" : 10, "truncated" : 0 }
{ "data" : -8.99, "rounded" : -10, "truncated" : 0 }
{ "data" : -8.45, "rounded" : -10, "truncated" : 0 }
{ "data" : -8.451, "rounded" : -10, "truncated" : 0 }

Esta vez hay un marcado contraste entre los resultados producidos por los dos operadores. El $trunc operador produjo 0 para cada documento, mientras que el $round El operador devolvió varios valores, la mayoría de los cuales se redondearon hacia arriba o hacia abajo.

$suelo y $techo

Dos operadores más a tener en cuenta al realizar operaciones como esta son $floor y $ceil . Estos operadores funcionan de manera similar, pero ligeramente diferente.

  • $floor devuelve el más grande entero menor o igual que el número especificado
  • $ceil devuelve el menor entero mayor o igual que el número especificado.