Documentação
Introdução
As consultas são objetos na linguagem de consulta do MongoDB. find(query) retorna um
cursor, findOne(query) retorna o primeiro resultado e count(query) retorna a
quantidade de resultados.
people.find({ city: 'Recife', age: { $gte: 18 } });
people.findOne({ email: 'ana@example.com' });
people.count({ active: true });
people.find({}); // tudo
Os exemplos desta página usam esta coleção:
const app = new sorla();
app.useDb('docs');
app.db.createCollection('people');
const people = app.db.people;
people.insertMany([
{ _id: 1, name: 'Ana', age: 31, city: 'Recife', tags: ['dev', 'ops'], address: { zip: '50000-000' } },
{ _id: 2, name: 'Bruno', age: 17, city: 'Curitiba', tags: ['design'] },
{ _id: 3, name: 'Carla', age: 45, city: 'Recife', tags: [], manager: null },
{ _id: 4, name: 'Davi', age: 28, city: 'São Paulo' }
]);
find
people.find(query, projection?) // → Cursor
O cursor guarda os resultados; leia-os com toArray(), percorra-os com for…of, ordene, pagine e
muito mais, veja Cursores. projection escolhe os campos:
people.find({}, { name: 1 }).
findOne
people.findOne({ city: 'Recife' }); // cópia da Ana, o primeiro resultado na ordem de inserção
people.findOne({ name: 'Nobody' }); // null
people.findOne({ _id: 3 }, { name: 1 }); // { _id: 3, name: 'Carla' }
count
people.count(); // 4, todos os documentos
people.count({ city: 'Recife' }); // 2, sem copiar nada
Condições de campo
Um valor simples significa igualdade; um objeto de operadores significa condições que precisam ser todas verdadeiras:
people.find({ city: 'Recife' }); // igualdade
people.find({ age: { $gte: 18, $lt: 40 } }); // 18 ≤ age < 40: Ana, Davi
people.find({ city: 'Recife', age: { $gt: 40 } }); // vários campos: todos precisam bater (AND)
Operadores de comparação
| Operador | Corresponde quando o campo… | Exemplo |
|---|---|---|
$eq |
é igual ao valor | { age: { $eq: 31 } } (o mesmo que { age: 31 }) |
$ne |
é diferente dele (inclusive quando o campo não existe) | { city: { $ne: 'Recife' } } |
$gt, $gte |
é maior (ou igual) | { age: { $gt: 30 } } |
$lt, $lte |
é menor (ou igual) | { age: { $lte: 17 } } |
$in |
é igual a um dos valores (ou, num campo array, contém um deles) | { city: { $in: ['Recife', 'Curitiba'] } } |
$nin |
não é igual a nenhum deles (inclusive quando não existe) | { tags: { $nin: ['dev'] } } |
$exists |
existe (true) ou não (false) |
{ manager: { $exists: true } } → Carla |
$regex |
é uma string que bate com um padrão | { name: { $regex: '^c', $options: 'i' } } |
$not |
não satisfaz a condição interna | { age: { $not: { $gte: 18, $lte: 40 } } } → Bruno, Carla |
As comparações funcionam com números, strings (por code point: 'B' < 'a') e objetos Date (pelo
tempo).
$in e $nin
people.find({ city: { $in: ['Recife', 'São Paulo'] } }); // Ana, Carla, Davi
people.find({ tags: { $in: ['ops', 'design'] } }); // Ana, Bruno: campos array contêm um deles
people.find({ name: { $in: [/^a/i, 'Davi'] } }); // expressões regulares batem com strings
people.find({ city: { $nin: ['Recife'] } }); // Bruno, Davi
$in e $nin exigem um array: The $in operator must be an array.
$regex
people.find({ name: { $regex: 'an' } }); // diferencia maiúsculas: nenhum
people.find({ name: { $regex: 'an', $options: 'i' } }); // Ana
people.find({ name: /^b/i }); // um valor RegExp funciona diretamente
people.find({ tags: { $regex: '^de' } }); // arrays batem quando uma das strings bate
$options aceita i (ignora maiúsculas/minúsculas), m (multilinha) e s (o ponto também casa
com quebras de linha). Valores que não são string nunca batem. Para buscar um texto digitado pelo
usuário, escape-o:
const escape = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
people.find({ name: { $regex: escape(input), $options: 'i' } });
$exists, campos ausentes e null
| Consulta | Ana (sem manager) |
Carla (manager: null) |
|---|---|---|
{ manager: null } |
✔ | |
{ manager: { $exists: true } } |
✔ | |
{ manager: { $exists: false } } |
✔ | |
{ manager: { $eq: 'x' } }, $gt, $in… |
||
{ manager: { $ne: 'x' } }, $nin |
✔ | ✔ |
Um campo ausente bate com $ne e $nin, como no MongoDB. Diferente do MongoDB, { field: null }
só encontra documentos em que o campo é null; para encontrar documentos sem o campo, use
{ field: { $exists: false } }, e para os dois casos,
{ $or: [{ field: null }, { field: { $exists: false } }] }.
Operadores lógicos
// OR: qualquer pessoa de Curitiba, ou com mais de 40 anos
people.find({ $or: [{ city: 'Curitiba' }, { age: { $gt: 40 } }] }); // Bruno, Carla
// AND escrito explicitamente (útil para repetir um campo)
people.find({ $and: [{ age: { $gte: 18 } }, { age: { $ne: 31 } }] }); // Carla, Davi
// NOR: nenhuma das condições
people.find({ $nor: [{ city: 'Recife' }, { age: { $lt: 18 } }] }); // Davi
// aninhe em qualquer nível e misture com campos
people.find({
age: { $gte: 18 },
$or: [
{ city: 'Recife', tags: { $in: ['dev'] } },
{ $and: [{ city: 'São Paulo' }, { name: { $regex: '^d', $options: 'i' } }] }
]
}); // Ana, Davi
| Operador | Valor | Corresponde quando |
|---|---|---|
$and |
array de consultas | todas batem |
$or |
array de consultas | pelo menos uma bate |
$nor |
array de consultas | nenhuma bate |
$not |
uma condição, dentro de um campo | a condição não é verdadeira |
Operadores lógicos precisam receber um array; operadores desconhecidos lançam um erro. A avaliação
para cedo: $and no primeiro falso, $or no primeiro verdadeiro.
Campos aninhados
Caminhos com ponto acessam o interior dos objetos:
people.find({ 'address.zip': '50000-000' }); // Ana
people.find({ 'address.zip': { $regex: '^5' } });
Arrays
people.find({ tags: { $in: ['dev'] } }); // contém 'dev'
people.find({ tags: { $exists: true } }); // tem o campo (o array vazio da Carla conta)
people.find({ tags: [] }); // igualdade em arrays não é suportada: use $in / $exists
A igualdade é estrita: { tags: 'dev' } não bate com tags: ['dev', 'ops']. Use $in.
Consultas por _id usam o índice
{ _id: x }, { _id: { $eq: x } } e { _id: { $in: [...] } } vão direto aos documentos pelo
índice da coleção, em vez de percorrer tudo, em find, findOne, count, em toda atualização e
exclusão, e em bulkWrite. As outras condições da mesma consulta continuam sendo verificadas:
people.find({ _id: { $in: [3, 1, 99] } }).ids(); // [1, 3], na ordem da coleção
people.find({ _id: 1, age: { $gt: 40 } }).length; // 0
Compartilhando consultas com um servidor
As consultas são JSON puro (exceto valores RegExp: use { $regex, $options } no lugar), então você
pode enviar o mesmo objeto para um backend MongoDB, guardá-lo ou montá-lo com uma interface de
construção de consultas:
const query = { $and: [{ age: { $gte: 30 } }, { $or: [{ name: 'Ana' }, { city: { $in: ['A', 'B'] } }] }] };
fetch('/api/people?where=' + encodeURIComponent(JSON.stringify(query)));
people.find(query); // o mesmo resultado localmente