Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

Modificar resultados de queries

En esta guía, puedes aprender cómo personalizar la manera en que Mongoid devuelve los resultados de las consultas. MongoDB te permite realizar las siguientes acciones para modificar la forma en que aparecen los resultados:

  • Retornar campos especificados

  • Ordenar resultados

  • Paginación de resultados

  • Cargar con entusiasmo las asociaciones

  • Devolver datos sin formato

Los ejemplos de esta guía utilizan el Band modelo, que representa una banda o grupo musical. La definición del modelo Band podría ser diferente para cada sección para demostrar diferentes funcionalidades de queries. Algunas secciones también utilizan el modelo Manager, que representa a una persona que gestionado una banda en particular, o el modelo Tour, que representa las presentaciones en vivo de la banda.

En MongoDB, la proyección es el proceso de especificar los campos a incluir o excluir de los resultados. Mongoid proporciona los siguientes operadores para proyectar campos:

  • only: Especifica los campos a incluir

  • without: Especifica los campos que se excluirán

El método only recupera solo los campos especificados de la base de datos.

El siguiente código devuelve solo el campo name de los documentos en los que el valor del campo members es 4:

Band.where(members: 4).only(:name)

Nota

Campo _id

En MongoDB, el campo _id se incluye en los resultados incluso si no lo incluyes explícitamente.

Si intentas hacer referencia a atributos que no se han cargado, Mongoid genera un error Mongoid::Errors::AttributeNotLoaded.

También puedes usar el método only para incluir campos de documentos incrustados.

Tenga en cuenta que el modelo Band incrusta múltiples objetos Tour. Puedes proyectar campos del modelo Tour como year, como se muestra en el siguiente código:

bands = Band.only(:name, 'tours.year')

Después, puedes acceder a los campos incrustados de los documentos devueltos:

# Returns the first Tour object from
# the first Band in the results
bands.first.tours.first

Puede pasar campos de asociaciones referenciadas al método only, pero la proyección se ignora al cargar los objetos incrustados. Mongoid carga todos los campos de las asociaciones referenciadas. Por ejemplo, cuando accedas al objeto Tour incrustado como se muestra en el código anterior, Mongoid devuelve el objeto completo, no solo el campo year.

Nota

Si está conectado a una implementación que ejecuta MongoDB 4.4 o posterior, no puede especificar una asociación y sus campos en una proyección en la misma query.

Si un documento contiene asociaciones has_one o has_and_belongs_to_many, y quieres que Mongoid cargue esas asociaciones cuando llames al método only, debes incluir los campos con claves externas en la lista de atributos.

En el siguiente ejemplo, los modelos Band y Manager tienen una asociación has_and_belongs_to_many:

class Band
include Mongoid::Document
field :name, type: String
has_and_belongs_to_many :managers
end
class Manager
include Mongoid::Document
has_and_belongs_to_many :bands
end

El siguiente código demuestra cómo Mongoid puede cargar los objetos Manager asociados si incluyes el campo manager_ids:

# Returns null
Band.where(name: 'Astral Projection').only(:name).first.managers
# Returns the first Manager object
Band.where(name: 'Astral Projection').only(:name, :manager_ids).first.managers

Puedes excluir explícitamente campos de los resultados utilizando el método without.

El siguiente código excluye el campo year de los objetos Band devueltos:

Band.where(members: 4).without(:year)

Importante

Campo _id

Mongoid requiere el campo _id para varias operaciones, por lo que no se puede excluir el campo _id ni el alias id de los resultados. Si pasas _id o id al método without, Mongoid lo ignorará.

Se puede especificar el orden en el que Mongoid devuelve documentos usando los métodos order y order_by.

Estos métodos aceptan un hash que indica por qué campos debe ordenarse los documentos, y si se utiliza un orden ascendente o descendente para cada campo.

Puedes especificar la dirección de orden usando números enteros, símbolos o cadenas. Recomendamos utilizar la misma sintaxis de clasificación en toda la aplicación para mantener la coherencia. La siguiente lista proporciona cada sintaxis y muestra cómo ordenar los campos name y year:

  • Enteros 1 (ascendente) y -1 (descendente)

    • Ejemplo: Band.order(name: 1, year: -1)

  • Símbolos :asc y :desc

    • Ejemplo: Band.order(name: :asc, year: :desc)

  • Cadenas "asc" y "desc"

    • Ejemplo: Band.order_by(name: "asc", year: "desc")

El método order también admite las siguientes especificaciones de ordenamiento:

  • Arreglo de matrices de dos elementos:

    • Strings

      • Ejemplo: Band.order([['name', 'asc'], ['year', 'desc']])

    • Símbolos

      • Ejemplo: Band.order([[:name, :asc], [:year, :desc]])

  • asc y desc métodos en símbolos

    • Ejemplo: Band.order(:name.asc, :year.desc)

  • Sintaxis SQL

    • Ejemplo: Band.order('name asc', 'year desc')

Tip

En lugar de usar order o order_by, también puedes usar los métodos asc y desc para especificar órdenes de clasificación:

Band.asc('name').desc('year')

Cuando encadenas especificaciones de ordenamiento, la primera llamada define el primer orden de clasificación y la llamada más reciente define el último orden de clasificación, después de aplicar los ordenamientos previos.

Nota

Ordenación en Alcances

Si define un ámbito por defecto en tu modelo que incluye una especificación de orden, la orden del ámbito tiene prioridad sobre el orden especificado en una query, porque el ámbito por defecto se evalúa primero.

Mongoid proporciona los métodos de paginación limit, skip y batch_size que puedes usar en objetos Criteria. Las siguientes secciones describen cómo utilizar estos operadores.

Puede utilizar el método limit para limitar el número de resultados que Mongoid devuelve.

El siguiente código recupera un máximo de 5 documentos:

Band.limit(5)

Nota

Alternativamente, puedes usar el método take para recuperar un número especificado de documentos de la base de datos:

Band.take(5)

Puedes omitir una cantidad específica de resultados utilizando el método skip, o su alias offset.

Si encadena una llamada limit con skip, el límite se aplica después de omitir los documentos, como se demuestra en el siguiente ejemplo:

Band.skip(2).limit(5)
# Skips the first two results and returns
# the following five results

Tip

Cuando se realice la paginación, use skip en resultados ordenados para garantizar resultados coherentes.

El siguiente código omite los primeros 3 documentos al devolver los resultados:

Band.skip(3)
# Equivalent
Band.offset(3)

Cuando se ejecutan grandes queries y se itera sobre los resultados de una query usando un método enumerador como Criteria#each, Mongoid utiliza automáticamente el comando MongoDB getMore para cargar los resultados en lotes. El tamaño de agrupar predeterminado es 1000, pero puedes establecer un valor diferente usando el método batch_size.

El siguiente código establece el tamaño del lote en 500:

Band.batch_size(500)

Cuando query documentos con asociaciones, el proceso de carga ansiosa permite cargar los documentos asociados al mismo tiempo que los documentos base, en lugar de cargarlos de forma diferida más tarde. Esto reduce el número de consultas a la base de datos y mejora el rendimiento para cargas de trabajo con muchas asociaciones. Mongoid proporciona dos métodos para cargar previamente documentos asociados cuando se consulta documentos con asociaciones: includes y eager_load.

El método includes carga asociaciones utilizando consultas separadas para cada asociación. El siguiente código carga las bandas y sus álbumes y sellos asociados usando consultas separadas:

Band.where(name: 'The Beatles').includes({ albums: :songs }, :labels).first

Cuando utilizas el método includes, Mongoid ejecuta una query en la clase base para obtener todos los documentos base y, a continuación, una query independiente para cada asociación que carga de forma anticipada.

El ejemplo anterior ejecuta las siguientes consultas:

  • Una sola query para encontrar los documentos Band

  • Una query para cargar los documentos asociados de Album

  • Una query para cargar los documentos asociados de Label

  • Una query para cargar los documentos asociados de Song

El método eager_load utiliza la pipeline de agregación de MongoDB con $lookup operadores para cargar todas las asociaciones en una sola consulta. El siguiente código utiliza una única consulta de pipeline de agregación para cargar bandas y sus álbumes y sellos asociados, con $lookup etapas para cada asociación:

Band.where(name: 'The Beatles').eager_load({ albums: :songs }, :labels).first

Ambos métodos includes y eager_load realizan una carga ansiosa, pero lo hacen de diferentes maneras. El método includes ejecuta una query para los documentos base y luego queries separadas para cada asociación. El método eager_load utiliza un solo pipeline de agregación con $lookup etapas para cargar las asociaciones.

El método eager_load ejecuta menos consultas y utiliza menos memoria que includes. Sin embargo, la eficiencia del método difiere según el tipo de asociaciones en tus documentos:

  • eager_load es más rápido para has_many, has_and_belongs_to_many y la carga de múltiples asociaciones en la mayoría de los conjuntos de datos

  • includes es más rápido para belongs_to, has_one y asociaciones anidadas en la mayoría de los conjuntos de datos

Elige el método que mejor se adapte a tu caso de uso y tipos de asociaciones.

Puedes devolver resultados como hashes en bruto sin crear instancias de modelos encadenando el método raw a tu query.

El siguiente código recupera los resultados de la query como hashes sin procesar:

Band.where(country: 'Argentina').raw

Por defecto, el método raw devuelve los documentos exactamente como Mongoid los recibe de la base de datos. Opcionalmente, se puede convertir los campos en las variables hash de resultados a los tipos de las declaraciones de campos del modelo estableciendo la opción typed en true en el método raw:

Band.where(country: 'Argentina').raw(typed: true)

Si se realiza una query que devuelve resultados en bruto y más tarde se desea convertir estos resultados en modelos, se puede llamar a raw(false) en los resultados:

# Retrieves raw results
results = Band.where(members: 4).raw
# ... Perform actions on results
# Returns instantiated model objects from raw results
bands = results.raw(false).to_a

Para obtener un catálogo completo de los métodos que puedes usar en Criteria objetos para modificar los resultados de la query, consulta la referencia del módulo Mongoid::Criteria::Queryable en la documentación de la API.

Para obtener más información sobre cómo construir queries, consulte la guía Especificar una query de documento.

Para aprender sobre el modelado de datos de Mongoid, consulte las guías de Modelar los datos.

Volver

Operaciones CRUD

En esta página