domingo, 28 de abril de 2013

The Little MongoDB Book - Capítulo 3 - Dominando a Pesquisa

No capítulo 1 demos uma olhada superficial no comando find.  No entando, há muito mais para aprender sobre esse seletor.  Vamos então ver mais detalhes sobre isso

Seleção de Campo

Antes de falarmos sobre cursores, você deve saber que o comando find possuiu um segundo parâmetro opcional.  Este parâmetro é a lista de campos que deseja recuperar.  Por exemplo, podemos obter todos os nomes dos unicórnios executando:

db.unicorns.find(null, {name: 1});

Por padrão, o campo id é sempre retornado.  Nós podemos excluí-lo explicitamente acrescentando _id:0 a lista de campos: {name: 1, _id: 0}

Não é possível combinar inclusão e exclusão de campos.  Se pensar sobre isso, concluirá que realmente faz sentido.  Ou você quer incluir ou excluir explicitamente um ou mais campos.

Ordenação


Algumas vezes mencionei que find retorna um cursor cuja execução é adiada até que seja necessária.  No entanto, observando através do shell, não temos dúvida de que sua execução é imediata.  Este é um comportamento apenas do shell.  

Podemos observar o verdadeiro comportamento dos cursores analisando um dos métodos do find.  O primeiro que analisaremos é o sort. O método sort funciona semelhante a seleção de campos que vimos na seção anterior.  Nós especificamos os campos que queremos usar para ordenar o cursor, usando 1 para ordem acedente e -1 para ordem descendente:  Por exemplo:

// mais pesados primeiros
db.unicorns.find().sort({weight: -1})

// pelo nome do unicorno e depois por quem mata vampiro
db.unicorns.find().sort({name: 1, vampires: -1})
Tal como acontece em um banco relacional, MondoDB pode usar índice para a ordenação.  Veremos mais detalhes sobre índice mais adiante.  No entanto, você deve saber que MongoDB limita o tamanho do seu sort quando não encontrar um índice.  Ou seja, se você tentar ordenar um grande conjunto de resultados sem o auxilio de um índice, vai obter um erro.  
Algumas pessoas vêem isso como uma limitação.  Na verdade, eu gostaria que mais bancos de dados tivessem a capacidade de recusar a executar comandos não otimizados.  (Não pretendo transformar cada desvantagem do MongoDB em um ponto positivo, mas já vi bancos de dados tão mal otimizados que sinceramente gostaria que eles tivessem um strict-mode)

Paginação

Para realizar a paginação dos resultados de um cursor, podemos usar o limit e o skip.  Para obter o segundo e terceiro unicórnio mais pesado, poderíamos executar:
db.unicorns.find()
   .sort({weight: -1})
   .limit(2)
   .skip(1)
Usar limit juntamente com sort, é uma boa maneira de evitar problemas quando ordenamos por campos não indexados.

Contar

O shell permite executar o comando count diretamente em um coleção, tal como:
db.unicorns.count({vampires: {$gt: 50}})
Na realidade, count é um método de cursor. O shell apenas simplifica seu uso providenciando um atalho.  Em drivers que não fornecem tal atalho é necessário executar desta forma (o qual irá funcionar no shell também):
db.unicorns.find({vampires: {$gt: 50}}).count()

Neste capítulo

Usar o find e cursors é bem simples.  Existem alguns comandos, que iremos conhecer nos próximos capítulos, que servem para casos mais extremos, mas por hora isso é suficiente para que você trabalhe confortavelmente no shell entendendo os fundamentos do MongoDB.