Learn the "why" behind slow queries and how to fix them in our 2-Part Webinar.
Register now >
Menu Docs
Página inicial do Docs
/ /

Modificar Resultados da Query

Neste guia, você pode aprender a personalizar a maneira como o Mongoid retorna resultados de queries. O MongoDB permite que você execute as seguintes ações para modificar a forma como os resultados aparecem:

  • Retornar campos especificados

  • Classificar resultados

  • Paginar resultados

  • Associações de carga ávida

  • Retornar dados brutos

Os exemplos deste guia usam o modelo Band, que representa uma banda ou grupo social. A definição do modelo Band pode ser diferente para cada seção para demonstrar diferentes funcionalidades de consulta. Algumas seções também usam o modelo Manager, que representa uma pessoa que gerencia uma determinada banda, ou o modelo Tour, que representa atuações ao vivo de uma determinada banda.

No MongoDB, projeção é o processo de especificar campos a serem incluídos ou excluídos dos resultados. O Mongoid fornece os seguintes operadores para projeto campos:

  • only: especifica os campos a serem incluídos

  • without: especifica os campos a serem excluídos

O método only recupera somente os campos especificados do banco de dados.

O código a seguir retorna apenas o campo name de documentos nos quais o valor do campo members é 4:

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

Observação

Campo _id

No MongoDB, o campo _id é incluído nos resultados mesmo que você não o inclua explicitamente.

Se você tentar referenciar atributos que não foram carregados, o Mongoid gerará um erro Mongoid::Errors::AttributeNotLoaded.

Você também pode usar o método only para incluir campos de documentos incorporados.

Considere que o modelo Band incorpora vários objetos Tour . Você pode projeto campos do modelo Tour como year, conforme mostrado no código a seguir:

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

Em seguida, você pode acessar os campos incorporados a partir dos documentos retornados:

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

Você pode passar campos de associações referenciadas para o método only, mas a projeção é ignorada ao carregar os objetos embarcados. O Mongoid carrega todos os campos das associações referenciadas. Por exemplo, quando você acessa o objeto Tour incorporado, conforme mostrado no código anterior, o Mongoid retorna o objeto completo, não apenas o campo year.

Observação

Se você estiver conectado a uma implantação executando o MongoDB 4.4 ou posterior, não poderá especificar uma associação e seus campos em uma projeção na mesma query.

Se um documento contiver associações has_one ou has_and_belongs_to_many e você quiser que o Mongoid carregue essas associações quando chamar o método only, será necessário incluir os campos com chaves estrangeiras na lista de atributos.

No exemplo seguinte, os modelos Band e Manager têm uma associação 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

O código a seguir demonstra como o Mongoid pode carregar os objetos Manager associados se você incluir o 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

Você pode excluir campos explicitamente dos resultados usando o método without.

O seguinte código exclui o campo year dos objetos Band retornados:

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

Importante

Campo _id

O Mongoid requer o _id campo para várias operações, portanto você não pode excluir o _id campo ou o id nome alternativo dos resultados. Se você passar _id ou id para o método without, o Mongoid o ignorará.

Você pode especificar a ordem em que o Mongoid retorna documentos usando os métodos order e order_by.

Esses métodos aceitam um hash que indica por quais campos os documentos devem ser ordenados e se uma ordem crescente ou decrescente para cada campo deve ser usada.

Você pode especificar a direção de classificação usando números inteiros, símbolos ou strings. Recomendamos usar a mesma sintaxe de classificação em todo o aplicação para obter consistência. A lista a seguir fornece cada sintaxe e mostra como classificar nos campos name e year:

  • Inteiros 1 (ascendente) e -1 (descendente)

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

  • Símbolos :asc e :desc

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

  • Strings "asc" e "desc"

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

O método order também aceita as seguintes especificações de classificação:

  • Array de arrays de dois elementos:

    • Strings

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

    • Símbolos

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

  • asc e métodos desc em símbolos

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

  • sintaxe SQL

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

Dica

Em vez de utilizar order ou order_by, você também pode utilizar os métodos asc e desc para especificar ordens de classificação:

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

Quando você encadeia especificações de classificação, a primeira chamada define a primeira ordem de classificação e a chamada mais recente define a última ordem de classificação depois que as classificações anteriores têm sido aplicadas.

Observação

Classificação em escopos

Se você definir um escopo padrão no seu modelo que inclua uma especificação de classificação, a classificação do escopo terá precedência sobre a classificação especificada em uma query, pois o escopo padrão é avaliado primeiro.

O Mongoid fornece os métodos de paginação limit, skip e batch_size que você pode usar em objetos Criteria . As seções a seguir descrevem como usar esses operadores.

Você pode usar o método limit para limitar o número de resultados que o Mongoid retorna.

O seguinte código recupera um máximo de 5 documentos:

Band.limit(5)

Observação

Alternativamente, você pode usar o método take para recuperar um número específico de documentos do banco de dados:

Band.take(5)

Você pode ignorar um número específico de resultados usando o método skip ou seu alias offset.

Se você encadear uma chamada limit para skip, o limite será aplicado depois que os documentos forem ignorados, conforme demonstrado no exemplo a seguir:

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

Dica

Ao realizar a paginação, use skip em resultados classificados para garantir resultados consistentes.

O seguinte código ignora os primeiros 3 documentos ao retornar resultados:

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

Ao executar query grandes e ao iterar sobre os resultados da query usando um método enumerador Criteria#each como, o Mongoid usa automaticamente o comando getMore do MongoDB para carregar os resultados em lotes. O tamanho do lote padrão é 1000, mas você pode definir um valor diferente usando o método batch_size.

O seguinte código define o tamanho do lote para 500:

Band.batch_size(500)

Quando você query documentos com associações, o carregamento rápido permite que você carregue os documentos associados ao mesmo tempo que os documentos base, em vez de carregá-los lentamente mais tarde. Isso reduz o número de queries ao banco de dados e melhora o desempenho para cargas de trabalho com muita associação. O Mongoid fornece dois métodos para carregar documentos associados quando você faz query de documentos com associações: includes e eager_load.

O método includes carrega associações utilizando queries separadas para cada associação. O código a seguir carrega bandas e seus discos e etiquetas associados utilizando queries separadas:

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

Quando você usa o método includes, o Mongoid executa uma query na classe base para obter todos os documentos de base e, em seguida, uma query separada para cada associação que ele carrega.

O exemplo anterior executa as seguintes queries:

  • Uma query para encontrar os documentos Band

  • Uma query para carregar os documentos Album associados

  • Uma query para carregar os documentos Label associados

  • Uma query para carregar os documentos Song associados

O método eager_load utiliza o pipeline de agregação MongoDB com operadores $lookup para carregar todas as associações em uma única query. O código a seguir usa uma única query de pipeline de agregação para carregar as bandas e seus discos e rótulos associados, com $lookup estágios para cada associação:

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

Os métodos includes e eager_load executam carregamento rápido, mas o fazem de maneiras diferentes. O método includes executa uma query para os documentos base e, em seguida, queries separadas para cada associação. O método eager_load utiliza um único pipeline de agregação com estágios $lookup para carregar as associações.

O método eager_load executa menos queries e utiliza menos memória do que includes. No entanto, a eficiência do método difere com base no tipo de associações em seus documentos:

  • eager_load é mais rápido para has_many, has_and_belongs_to_many e carregando múltiplas associações na maioria dos conjuntos de dados

  • includes é mais rápido para belongs_to, has_one e associações aninhadas na maioria dos conjuntos de dados

Escolha o método que melhor se adequa ao seu caso de uso e tipos de associação.

Você pode retornar resultados como hashes brutos sem criar instâncias de modelo encadeando o método raw à sua query.

O seguinte código recupera os resultados da query como hashes brutos:

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

Por padrão, o método raw retorna documentos exatamente como o Mongoid os recebe do banco de dados. Opcionalmente, você pode converter campos em seus hashes de resultado para os tipos de declarações de campo de modelo definindo a opção typed como true no método raw:

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

Se você executar uma query que retorna resultados brutos e, posteriormente, quiser converter esses resultados em modelos, poderá chamar raw(false) nos 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 obter um catálogo completo de métodos que você pode usar em objetos Criteria para modificar os resultados da query, consulte a referência do módulo Mongoid::Criteria::Queryable na documentação da API.

Para saber mais sobre a construção de queries, consulte o guia Especificar uma consulta ao documento.

Para saber mais sobre a modelagem de dados Mongoid, consulte os guias Modele seus dados.

Voltar

Operações CRUD

Nesta página