Almost every screen in an app is backed by a find query.
find(filter, projection) returns a cursor over matching documents; findOne returns the first match or null. The filter is itself a document: { status: "paid" } means status equals "paid", and several fields are combined with AND: { status: "paid", country: "AM" }. An empty filter {} matches everything.
To reach inside embedded documents use dot notation with quotes: { "customer.email": "ana@example.com" }. Matching a whole embedded document, { customer: { email: "..." } }, instead requires an exact match of the entire subdocument including field order, which is rarely what you want.
The projection limits which fields come back, saving bandwidth:
{ name: 1, price: 1 }returns only those fields plus_id,{ _id: 0, name: 1 }also drops_id,{ description: 0 }returns everything exceptdescription.
You cannot mix inclusions and exclusions in one projection, except for excluding _id.
A null filter value matches both documents where the field is null and documents where it is missing. To test presence explicitly use { field: { $exists: true } }, covered with the other operators next.
Example
db.users.insertMany([
{ name: "Ana", age: 31, address: { city: "Yerevan" }, tags: ["admin"] },
{ name: "Ben", age: 25, address: { city: "Gyumri" } },
{ name: "Cy", age: 31, address: { city: "Yerevan" }, nickname: null }
])
db.users.find({ "address.city": "Yerevan", age: 31 }, { _id: 0, name: 1 })
// [ { name: 'Ana' }, { name: 'Cy' } ]
db.users.findOne({ name: "Ben" }, { address: 0, _id: 0 })
// { name: 'Ben', age: 25 }
db.users.find({ nickname: null }, { _id: 0, name: 1 })
// Ana, Ben and Cy: null also matches a missing fieldRemember
- Filter fields are ANDed; {} matches everything
- Use "a.b" dot notation to filter on embedded fields
- Projection: 1 to include, 0 to exclude, never both (except _id)
- { field: null } matches null and missing
Watch out for
- Filtering with a whole subdocument { address: { city: 'X' } }, which needs an exact match of the entire object.