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
/ /

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

  • Asociaciones de carga ansiosas

  • Devolver datos sin procesar

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, laproyección es el proceso de especificar los campos que se incluirán o excluirán 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 incluye 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 incorpora varios objetos Tour. Puede 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

Se pueden 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, al acceder al objeto incrustado Tour, 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 consulta.

Si un documento contiene asociaciones has_one o has_and_belongs_to_many y desea que Mongoid cargue esas asociaciones cuando llame al método only, debe 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 incluye 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:

  • Matriz 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 utilizar order o order_by, también puede utilizar 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 defines una alcance predeterminado en su modelo que incluye una especificación de ordenamiento, el ordenamiento del alcance tiene prioridad sobre el ordenamiento especificado en una consulta, porque el alcance predeterminado 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 a skip, el límite se aplica después de omitir los documentos, como se muestra 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)

Al consultar documentos con asociaciones, la carga anticipada permite cargar los documentos asociados al mismo tiempo que los documentos base, en lugar de cargarlos posteriormente de forma diferida. Esto reduce el número de consultas a la base de datos y mejora el rendimiento en cargas de trabajo con gran cantidad de asociaciones. Mongoid ofrece dos métodos para cargar anticipadamente los documentos asociados al consultar documentos con asociaciones: includes y eager_load.

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

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

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

El ejemplo anterior ejecuta las siguientes consultas:

  • Una consulta para encontrar los documentos Band

  • Una consulta para cargar los documentos Album asociados

  • Una consulta para cargar los documentos Label asociados

  • Una consulta para cargar los documentos Song asociados

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

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

Los métodos includes y eager_load realizan una carga anticipada, pero de maneras diferentes. El método includes ejecuta una consulta para los documentos base y luego consultas separadas para cada asociación. El método eager_load utiliza una única canalización de agregación con $lookup etapas para cargar las asociaciones.

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

  • eager_load es más rápido para has_many, has_and_belongs_to_many y para cargar 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

Elija el método que mejor se adapte a su caso de uso y tipos de asociación.

Puedes devolver los resultados como hashes sin procesar sin crear instancias del modelo encadenando el método raw a tu consulta.

El siguiente código recupera los resultados de la consulta 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, puede convertir los campos de sus hashes de resultados a los tipos de las declaraciones de campos de su modelo configurando la opción typed a true en el método raw:

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

Si realiza una consulta que devuelve resultados sin procesar y posteriormente desea convertir estos resultados en modelos, 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 consultas, consulte la guía Especificar una consulta 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