Docs Menu
Docs Home
/ /
Strategies

Utiliza índices para ordenar los resultados de las consultas

Dado que los índices contienen registros ordenados, MongoDB puede obtener los resultados de una clasificación de un índice que incluye los campos de clasificación. MongoDB puede usar varios índices para admitir una operación de ordenación si la ordenación utiliza los mismos índices que el predicado del query.

Si MongoDB no puede usar uno o más índices para obtener el orden de ordenación, debe realizar una ordenación por bloqueo de los datos. Esta ordenación indica que MongoDB debe consumir y procesar todos los documentos de entrada antes de devolver los resultados. Las ordenaciones por bloqueo no bloquean las operaciones concurrentes en la colección o la base de datos.

Si MongoDB necesita más de 100 megabytes de memoria del sistema para la operación de ordenamiento por bloqueo, MongoDB devuelve un error a menos que la consulta especifique cursor.allowDiskUse(). permite que MongoDB use archivos temporales en el disco para almacenar datos que excedenallowDiskUse() el 100 límite de memoria del sistema de megabytes mientras procesa una operación de clasificación por bloqueo.

Las operaciones de ordenamiento que utilizan un índice suelen tener un mejor rendimiento que los ordenamientos por bloqueo.

Nota

Como resultado de los cambios en el comportamiento de clasificación de los campos de matriz en MongoDB,4.4 cuando se ordena en una matriz indexada con un índice de clave múltiple, el plan de consulta incluye una etapa de clasificación de bloqueo, a menos que:

  • Los límites de índice para todos los campos de ordenación son [MinKey, MaxKey] y

  • Ningún límite para ningún campo indexado con múltiples claves tiene el mismo prefijo de ruta que el patrón de ordenación.

Si hay un índice ascendente o descendente en un solo campo, la operación de clasificación en el campo puede ser en cualquier dirección.

Por ejemplo, crea un índice ascendente en el campo a para una colección records:

db.records.createIndex( { a: 1 } )

Este índice puede admitir un orden ascendente en a:

db.records.find().sort( { a: 1 } )

El índice también puede admitir el siguiente orden descendente en a recorriendo el índice en orden inverso:

db.records.find().sort( { a: -1 } )

Crea un índice compuesto para admitir la clasificación en varios campos.

Puedes especificar un orden en todas las claves del índice o en un subconjunto; sin embargo, las claves de clasificación deben aparecer en el mismo orden en que aparecen en el índice. Por ejemplo, un patrón de clave de índice { a: 1, b: 1 } puede admitir un orden { a: 1, b: 1 } pero no { b: 1, a: 1 }.

Para que un query utilice un índice compuesto para una ordenación, la dirección de ordenación especificada para todas las claves del documento cursor.sort() debe coincidir con el patrón de claves del índice o coincidir con el inverso del patrón de claves del índice. Por ejemplo, un patrón de clave de índice { a: 1, b: -1 } puede admitir un orden { a: 1, b: -1 } y { a: -1, b: 1 } pero no { a: -1, b: -1 } o {a: 1, b: 1}.

Si las claves de ordenación se corresponden con las claves del índice o con un prefijo del índice, MongoDB puede utilizar el índice para ordenar los resultados del query. Un prefijo de un índice compuesto es un subconjunto que consiste en una o más claves al comienzo del patrón de clave de índice.

Por ejemplo, crea un índice compuesto en la colección data:

db.data.createIndex( { a:1, b: 1, c: 1, d: 1 } )

Entonces, estos son los prefijos de ese índice:

{ a: 1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }

Las siguientes operaciones de query y ordenación utilizan los prefijos de índice para ordenar los resultados. Estas operaciones no necesitan ordenar el conjunto de resultados en la memoria.

Ejemplo
Index Prefix

db.data.find().sort( { a: 1 } )

{ a: 1 }

db.data.find().sort( { a: -1 } )

{ a: 1 }

db.data.find().sort( { a: 1, b: 1 } )

{ a: 1, b: 1 }

db.data.find().sort( { a: -1, b: -1 } )

{ a: 1, b: 1 }

db.data.find().sort( { a: 1, b: 1, c: 1 } )

{ a: 1, b: 1, c: 1 }

db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } )

{ a: 1, b: 1 }

Analiza el siguiente ejemplo en el que las claves de prefijo del índice aparecen tanto en el predicado del query como en el orden:

db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } )

En tales casos, MongoDB puede utilizar el índice para recuperar los documentos en el orden especificado. Como se muestra en el ejemplo, el prefijo de índice en el predicado del query puede ser diferente del prefijo de la ordenación.

Un índice puede admitir operaciones de ordenación en un subconjunto del patrón de claves de índice que no sea prefijo. Para ello, el query debe incluir condiciones de igualdad en todas las claves de prefijo que preceden a las claves de ordenación.

Por ejemplo, la colección data tiene el siguiente índice:

{ a: 1, b: 1, c: 1, d: 1 }

Las siguientes operaciones pueden utilizar el índice para obtener el orden de ordenación:

Ejemplo
Index Prefix

db.data.find( { a: 5 } ).sort( { b: 1, c: 1 } )

{ a: 1 , b: 1, c: 1 }

db.data.find( { b: 3, a: 4 } ).sort( { c: 1 } )

{ a: 1, b: 1, c: 1 }

db.data.find( { a: 5, b: { $lt: 3} } ).sort( { b: 1 } )

{ a: 1, b: 1 }

Como muestra la última operación, solo los campos de índice que preceden al subconjunto de ordenación deben tener las condiciones de igualdad en el documento de query; los otros campos de índice pueden especificar otras condiciones.

Si el query no especifica una condición de igualdad en un prefijo del índice que preceda o se solape con la especificación de ordenación, la operación no utilizará el índice de manera eficiente. Por ejemplo, las siguientes operaciones especifican un documento de ordenación de { c: 1 }, pero los documentos de query no contienen coincidencias exactas en los campos de índice anteriores a y b:

db.data.find( { a: { $gt: 2 } } ).sort( { c: 1 } )
db.data.find( { c: 5 } ).sort( { c: 1 } )

Estas operaciones no utilizarán el índice { a: 1, b: 1, c: 1, d: 1 } de forma eficaz y es posible que ni siquiera utilicen el índice para recuperar los documentos.

Una colección de documentos indexados puede tener múltiples tipos de datos en el campo clave.

  • Cuando un índice tiene una clave con varios tipos de datos, el índice se ordena según el orden de ordenación de tipo BSON.

  • En comparaciones de matrices:

    • Una ordenación ascendente compara los elementos más pequeños de la matriz según el orden de clasificación de tipo BSON.

    • Una ordenación descendente compara los elementos más grandes de la matriz según el orden de clasificación de tipo BSON inverso.

    • Losoperadores de consulta de comparación, como y, realizan $lt comparaciones en matrices lexicográficamente.$gt

    • Al comparar un campo cuyo valor es una matriz de un elemento (por ejemplo, [ 1 ]) con campos que no son matrices (por ejemplo, 2), la comparación es para 1 y 2.

    • Una comparación de una matriz vacía (por ejemplo, [ ]) considera que la matriz vacía es menor que un valor null o un valor de campo faltante.

    • Una comparación de una matriz anidada (por ejemplo, [[1, 2], [3, 4]]) compara lexicográficamente cualquier matriz después de la matriz más externa.

Consulta el ejemplo de ordenación del índice.

Para utilizar un índice para las comparaciones de cadenas, una operación también debe especificar la misma intercalación. Es decir, un índice con una intercalación no puede soportar una operación que realice comparaciones de strings en los campos indexados si la operación especifica una intercalación diferente.

Advertencia

Debido a que los índices configurados con intercalación utilizan claves de intercalación ICU para lograr el orden de clasificación, las claves de índice que consideran la intercalación pueden ser más grandes que las claves de índice para los índices sin intercalación.

Por ejemplo, la colección myColl tiene un índice en un campo de cadena category con la configuración regional de intercalación "fr".

db.myColl.createIndex( { category: 1 }, { collation: { locale: "fr" } } )

La siguiente operación de consulta, que especifica la misma intercalación que el índice, puede utilizar el índice:

db.myColl.find( { category: "cafe" } ).collation( { locale: "fr" } )

Sin embargo, la siguiente operación de query, que por defecto utiliza el intercalador binario "simple", no puede usarse el índice:

db.myColl.find( { category: "cafe" } )

Para un índice compuesto donde las claves prefijo del índice no son cadenas, arreglos ni documentos incrustados, una operación que especifique una intercalación diferente puede seguir utilizando el índice para soportar comparaciones en las claves prefijo del índice.

Por ejemplo, la colección myColl tiene un índice compuesto en los campos numéricos score y price y el campo de string category; el índice se crea con la localización de intercalación "fr" para comparaciones de strings:

db.myColl.createIndex(
{ score: 1, price: 1, category: 1 },
{ collation: { locale: "fr" } } )

Las siguientes operaciones, que utilizan la intercalación binaria "simple" para las comparaciones de strings, pueden usar el índice:

db.myColl.find( { score: 5 } ).sort( { price: 1 } )
db.myColl.find( { score: 5, price: { $gt: NumberDecimal( "10" ) } } ).sort( { price: 1 } )

La siguiente operación, que utiliza la intercalación binaria "simple" para las comparaciones de string en el campo category indexado, puede usar el índice para cumplir solo con la parte score: 5 de la query:

db.myColl.find( { score: 5, category: "cafe" } )

Importante

Las coincidencias con claves de documento, incluidas las claves de documento incrustadas, utilizan una comparación binaria simple. Esto significa que una consulta para una clave como "foo.bár" no coincidirá con la clave "foo.bar", independientemente del valor establecido para el parámetro de fuerza.

En el siguiente ejemplo, se demuestra la ordenación cuando los tipos de claves de índice son los mismos o son diferentes.

Crear la colección keyTypes:

db.keyTypes.insertMany( [
{ seqNum: 1, seqType: null, type: "null" },
{ seqNum: 29, seqType: null, type: "null" },
{ seqNum: 2, seqType: Int32("10"), type: "Int32" },
{ seqNum: 28, seqType: Int32("10"), type: "Int32" },
{ seqNum: 3, seqType: Long("10"), type: "Long" },
{ seqNum: 27, seqType: Long("10"), type: "Long" },
{ seqNum: 4, seqType: Decimal128("10"), type: "Decimal128" },
{ seqNum: 26, seqType: Decimal128("10"), type: "Decimal128" },
{ seqNum: 5, seqType: Double("10"), type: "Double" },
{ seqNum: 25, seqType: Double("10"), type: "Double" },
{ seqNum: 6, seqType: String("10"), type: "String" },
{ seqNum: 24, seqType: String("10"), type: "String" },
{ seqNum: 7, seqType: [ "1", "2", "3" ], type: "Array" },
{ seqNum: 23, seqType: [ "1", "2", "3" ], type: "Array" },
{ seqNum: 8, seqType: [ [1], [2], [3] ], type: "Array" },
{ seqNum: 22, seqType: [ [1], [2], [3] ], type: "Array " },
{ seqNum: 9, seqType: [ 1, 2, 3 ], type: "Array" },
{ seqNum: 21, seqType: [ 1, 2, 3 ], type: "Array" },
{ seqNum: 10, seqType: true, type: "Boolean" },
{ seqNum: 11, seqType: new Timestamp(), type: "Timestamp" },
{ seqNum: 12, seqType: new Date(), type: "Date" },
{ seqNum: 13, seqType: new ObjectId(), type: "ObjectId" },
] )

Crea índices en los campos de número de secuencia ( seqNum ) y tipo de secuencia ( seqType ):

db.keyTypes.createIndex( { seqNum: 1 } )
db.keyTypes.createIndex( { seqType: 1 } )

Realiza un query en la colección mediante find(). El documento de proyección, { _id: 0 }, suprime el campo _id en la visualización de salida.

db.keyTypes.find( {}, { _id: 0 } )

Los documentos se devuelven en orden de inserción:

{ seqNum: 1, seqType: null, type: 'null' },
{ seqNum: 29, seqType: null, type: 'null' },
{ seqNum: 2, seqType: 10, type: 'Int32' },
{ seqNum: 28, seqType: 10, type: 'Int32' },
{ seqNum: 3, seqType: Long("10"), type: 'Long' },
{ seqNum: 27, seqType: Long("10"), type: 'Long' },
{ seqNum: 4, seqType: Decimal128("10"), type: 'Decimal128' },
// Output truncated

El índice de número de secuencia ( seqNum ) tiene valores del mismo tipo. Utiliza el índice seqNum para realizar un query en la colección keyTypes:

db.keyTypes.find( {}, { _id: 0 } ).sort( { seqNum: 1} )

Las claves seqNum son números enteros. Los documentos se devuelven en orden numérico:

{ seqNum: 1, seqType: null, type: 'null' },
{ seqNum: 2, seqType: 10, type: 'Int32' },
{ seqNum: 3, seqType: Long("10"), type: 'Long' },
{ seqNum: 4, seqType: Decimal128("10"), type: 'Decimal128' },
{ seqNum: 5, seqType: 10, type: 'Double' },
{ seqNum: 6, seqType: '10', type: 'String' },
{ seqNum: 7, seqType: [ '1', '2', '3' ], type: 'Array' },
// Output truncated

El índice de tipo de secuencia ( seqType ) tiene valores de diferentes tipos. Utiliza el índice seqType para realizar un query en la colección keyTypes:

db.keyTypes.find( {}, { _id: 0 } ).sort( { seqType: 1} )

Los documentos se devuelven en el orden de ordenación de tipo BSON:

{ seqNum: 1, seqType: null, type: 'null' },
{ seqNum: 29, seqType: null, type: 'null' },
{ seqNum: 9, seqType: [ 1, 2, 3 ], type: 'Array' },
{ seqNum: 21, seqType: [ 1, 2, 3 ], type: 'Array' },
{ seqNum: 2, seqType: 10, type: 'Int32' },
{ seqNum: 28, seqType: 10, type: 'Int32' },
{ seqNum: 3, seqType: Long("10"), type: 'Long' },
{ seqNum: 27, seqType: Long("10"), type: 'Long' },
{ seqNum: 4, seqType: Decimal128("10"), type: 'Decimal128' },
{ seqNum: 26, seqType: Decimal128("10"), type: 'Decimal128' },
{ seqNum: 5, seqType: 10, type: 'Double' },
{ seqNum: 25, seqType: 10, type: 'Double' },
{ seqNum: 7, seqType: [ '1', '2', '3' ], type: 'Array' },
{ seqNum: 23, seqType: [ '1', '2', '3' ], type: 'Array' },
{ seqNum: 6, seqType: '10', type: 'String' },
{ seqNum: 24, seqType: '10', type: 'String' },
{ seqNum: 8, seqType: [ [ 1 ], [ 2 ], [ 3 ] ], type: 'Array' },
{ seqNum: 22, seqType: [ [ 1 ], [ 2 ], [ 3 ] ], type: 'Array ' },
{
seqNum: 13,
seqType: ObjectId("6239e3922604d5a7478df071"),
type: 'ObjectId'
},
{ seqNum: 10, seqType: true, type: 'Boolean' },
{
seqNum: 12,
seqType: ISODate("2022-03-22T14:56:18.100Z"),
type: 'Date'
},
{
seqNum: 11,
seqType: Timestamp({ t: 1647960978, i: 1 }),
type: 'Timestamp'
}
  • En comparaciones de matrices:

    • Una ordenación ascendente compara los elementos más pequeños de la matriz según el orden de clasificación de tipo BSON.

    • Una ordenación descendente compara los elementos más grandes de la matriz según el orden de clasificación de tipo BSON inverso.

    • Losoperadores de consulta de comparación, como y, realizan $lt comparaciones en matrices lexicográficamente.$gt

    • Al comparar un campo cuyo valor es una matriz de un elemento (por ejemplo, [ 1 ]) con campos que no son matrices (por ejemplo, 2), la comparación es para 1 y 2.

    • Una comparación de una matriz vacía (por ejemplo, [ ]) considera que la matriz vacía es menor que un valor null o un valor de campo faltante.

    • Una comparación de una matriz anidada (por ejemplo, [[1, 2], [3, 4]]) compara lexicográficamente cualquier matriz después de la matriz más externa.

  • Los tipos numéricos (Int32, Long, Decimal128, Double) son equivalentes en comparación con otros tipos.

  • Dentro del tipo BSON de números, se ordenan los tipos numéricos:

    • Int32

    • Long

    • Decimal128

    • Double

Volver

Consultas de soporte

En esta página