Finding documents

Use find to look for multiple documents matching you query, or findOne to look for one specific document. You can select documents based on field equality or use comparison operators ($lt, $lte, $gt, $gte, $in, $nin, $ne). You can also use logical operators $or, $and, $not and $where. See below for the syntax.

You can use regular expressions in two ways: in basic querying in place of a string, or with the $regex operator.

You can sort and paginate results using the cursor API (see below).

You can use standard projections to restrict the fields to appear in the results (see below).

Basic querying

Basic querying means are looking for documents whose fields match the ones you specify. You can use regular expression to match strings.You can use the dot notation to navigate inside nested documents, arrays, arrays of subdocuments and to match a specific element of an array.

  1. // Let's say our datastore contains the following collection
  2. // { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false, satellites: ['Phobos', 'Deimos'] }
  3. // { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true, humans: { genders: 2, eyes: true } }
  4. // { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
  5. // { _id: 'id4', planet: 'Omicron Persei 8', system: 'futurama', inhabited: true, humans: { genders: 7 } }
  6. // { _id: 'id5', completeData: { planets: [ { name: 'Earth', number: 3 }, { name: 'Mars', number: 2 }, { name: 'Pluton', number: 9 } ] } }
  7. // Finding all planets in the solar system
  8. db.find({ system: 'solar' }, function (err, docs) {
  9. // docs is an array containing documents Mars, Earth, Jupiter
  10. // If no document is found, docs is equal to []
  11. });
  12. // Finding all planets whose name contain the substring 'ar' using a regular expression
  13. db.find({ planet: /ar/ }, function (err, docs) {
  14. // docs contains Mars and Earth
  15. });
  16. // Finding all inhabited planets in the solar system
  17. db.find({ system: 'solar', inhabited: true }, function (err, docs) {
  18. // docs is an array containing document Earth only
  19. });
  20. // Use the dot-notation to match fields in subdocuments
  21. db.find({ "humans.genders": 2 }, function (err, docs) {
  22. // docs contains Earth
  23. });
  24. // Use the dot-notation to navigate arrays of subdocuments
  25. db.find({ "completeData.planets.name": "Mars" }, function (err, docs) {
  26. // docs contains document 5
  27. });
  28. db.find({ "completeData.planets.name": "Jupiter" }, function (err, docs) {
  29. // docs is empty
  30. });
  31. db.find({ "completeData.planets.0.name": "Earth" }, function (err, docs) {
  32. // docs contains document 5
  33. // If we had tested against "Mars" docs would be empty because we are matching against a specific array element
  34. });
  35. // You can also deep-compare objects. Don't confuse this with dot-notation!
  36. db.find({ humans: { genders: 2 } }, function (err, docs) {
  37. // docs is empty, because { genders: 2 } is not equal to { genders: 2, eyes: true }
  38. });
  39. // Find all documents in the collection
  40. db.find({}, function (err, docs) {
  41. });
  42. // The same rules apply when you want to only find one document
  43. db.findOne({ _id: 'id1' }, function (err, doc) {
  44. // doc is the document Mars
  45. // If no document is found, doc is null
  46. });

Operators ($lt, $lte, $gt, $gte, $in, $nin, $ne, $exists, $regex)

The syntax is { field: { $op: value } } where $op is any comparison operator:

  • $lt, $lte: less than, less than or equal
  • $gt, $gte: greater than, greater than or equal
  • $in: member of. value must be an array of values
  • $ne, $nin: not equal, not a member of
  • $exists: checks whether the document posses the property field. value should be true or false
  • $regex: checks whether a string is matched by the regular expression. Contrary to MongoDB, the use of $options with $regex is not supported, because it doesn't give you more power than regex flags. Basic queries are more readable so only use the $regex operator when you need to use another operator with it (see example below)
  1. // $lt, $lte, $gt and $gte work on numbers and strings
  2. db.find({ "humans.genders": { $gt: 5 } }, function (err, docs) {
  3. // docs contains Omicron Persei 8, whose humans have more than 5 genders (7).
  4. });
  5. // When used with strings, lexicographical order is used
  6. db.find({ planet: { $gt: 'Mercury' }}, function (err, docs) {
  7. // docs contains Omicron Persei 8
  8. })
  9. // Using $in. $nin is used in the same way
  10. db.find({ planet: { $in: ['Earth', 'Jupiter'] }}, function (err, docs) {
  11. // docs contains Earth and Jupiter
  12. });
  13. // Using $exists
  14. db.find({ satellites: { $exists: true } }, function (err, docs) {
  15. // docs contains only Mars
  16. });
  17. // Using $regex with another operator
  18. db.find({ planet: { $regex: /ar/, $nin: ['Jupiter', 'Earth'] } }, function (err, docs) {
  19. // docs only contains Mars because Earth was excluded from the match by $nin
  20. });

Array fields

When a field in a document is an array, NeDB first tries to see if the query value is an array to perform an exact match, then whether there is an array-specific comparison function (for now there is only $size and $elemMatch) being used. If not, the query is treated as a query on every element and there is a match if at least one element matches.

  • $size: match on the size of the array
  • $elemMatch: matches if at least one array element matches the query entirely
  1. // Exact match
  2. db.find({ satellites: ['Phobos', 'Deimos'] }, function (err, docs) {
  3. // docs contains Mars
  4. })
  5. db.find({ satellites: ['Deimos', 'Phobos'] }, function (err, docs) {
  6. // docs is empty
  7. })
  8. // Using an array-specific comparison function
  9. // $elemMatch operator will provide match for a document, if an element from the array field satisfies all the conditions specified with the `$elemMatch` operator
  10. db.find({ completeData: { planets: { $elemMatch: { name: 'Earth', number: 3 } } } }, function (err, docs) {
  11. // docs contains documents with id 5 (completeData)
  12. });
  13. db.find({ completeData: { planets: { $elemMatch: { name: 'Earth', number: 5 } } } }, function (err, docs) {
  14. // docs is empty
  15. });
  16. // You can use inside #elemMatch query any known document query operator
  17. db.find({ completeData: { planets: { $elemMatch: { name: 'Earth', number: { $gt: 2 } } } } }, function (err, docs) {
  18. // docs contains documents with id 5 (completeData)
  19. });
  20. // Note: you can't use nested comparison functions, e.g. { $size: { $lt: 5 } } will throw an error
  21. db.find({ satellites: { $size: 2 } }, function (err, docs) {
  22. // docs contains Mars
  23. });
  24. db.find({ satellites: { $size: 1 } }, function (err, docs) {
  25. // docs is empty
  26. });
  27. // If a document's field is an array, matching it means matching any element of the array
  28. db.find({ satellites: 'Phobos' }, function (err, docs) {
  29. // docs contains Mars. Result would have been the same if query had been { satellites: 'Deimos' }
  30. });
  31. // This also works for queries that use comparison operators
  32. db.find({ satellites: { $lt: 'Amos' } }, function (err, docs) {
  33. // docs is empty since Phobos and Deimos are after Amos in lexicographical order
  34. });
  35. // This also works with the $in and $nin operator
  36. db.find({ satellites: { $in: ['Moon', 'Deimos'] } }, function (err, docs) {
  37. // docs contains Mars (the Earth document is not complete!)
  38. });

Logical operators $or, $and, $not, $where

You can combine queries using logical operators:

  • For $or and $and, the syntax is { $op: [query1, query2, …] }.
  • For $not, the syntax is { $not: query }
  • For $where, the syntax is { $where: function () { / object is "this", return a boolean / } }
  1. db.find({ $or: [{ planet: 'Earth' }, { planet: 'Mars' }] }, function (err, docs) {
  2. // docs contains Earth and Mars
  3. });
  4. db.find({ $not: { planet: 'Earth' } }, function (err, docs) {
  5. // docs contains Mars, Jupiter, Omicron Persei 8
  6. });
  7. db.find({ $where: function () { return Object.keys(this) > 6; } }, function (err, docs) {
  8. // docs with more than 6 properties
  9. });
  10. // You can mix normal queries, comparison queries and logical operators
  11. db.find({ $or: [{ planet: 'Earth' }, { planet: 'Mars' }], inhabited: true }, function (err, docs) {
  12. // docs contains Earth
  13. });

Sorting and paginating

If you don't specify a callback to find, findOne or count, a Cursor object is returned. You can modify the cursor with sort, skip and limit and then execute it with exec(callback).

  1. // Let's say the database contains these 4 documents
  2. // doc1 = { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false, satellites: ['Phobos', 'Deimos'] }
  3. // doc2 = { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true, humans: { genders: 2, eyes: true } }
  4. // doc3 = { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
  5. // doc4 = { _id: 'id4', planet: 'Omicron Persei 8', system: 'futurama', inhabited: true, humans: { genders: 7 } }
  6. // No query used means all results are returned (before the Cursor modifiers)
  7. db.find({}).sort({ planet: 1 }).skip(1).limit(2).exec(function (err, docs) {
  8. // docs is [doc3, doc1]
  9. });
  10. // You can sort in reverse order like this
  11. db.find({ system: 'solar' }).sort({ planet: -1 }).exec(function (err, docs) {
  12. // docs is [doc1, doc3, doc2]
  13. });
  14. // You can sort on one field, then another, and so on like this:
  15. db.find({}).sort({ firstField: 1, secondField: -1 }) ... // You understand how this works!

Projections

You can give find and findOne an optional second argument, projections. The syntax is the same as MongoDB: { a: 1, b: 1 } to return only the a and b fields, { a: 0, b: 0 } to omit these two fields. You cannot use both modes at the time, except for _id which is by default always returned and which you can choose to omit. You can project on nested documents.

  1. // Same database as above
  2. // Keeping only the given fields
  3. db.find({ planet: 'Mars' }, { planet: 1, system: 1 }, function (err, docs) {
  4. // docs is [{ planet: 'Mars', system: 'solar', _id: 'id1' }]
  5. });
  6. // Keeping only the given fields but removing _id
  7. db.find({ planet: 'Mars' }, { planet: 1, system: 1, _id: 0 }, function (err, docs) {
  8. // docs is [{ planet: 'Mars', system: 'solar' }]
  9. });
  10. // Omitting only the given fields and removing _id
  11. db.find({ planet: 'Mars' }, { planet: 0, system: 0, _id: 0 }, function (err, docs) {
  12. // docs is [{ inhabited: false, satellites: ['Phobos', 'Deimos'] }]
  13. });
  14. // Failure: using both modes at the same time
  15. db.find({ planet: 'Mars' }, { planet: 0, system: 1 }, function (err, docs) {
  16. // err is the error message, docs is undefined
  17. });
  18. // You can also use it in a Cursor way but this syntax is not compatible with MongoDB
  19. db.find({ planet: 'Mars' }).projection({ planet: 1, system: 1 }).exec(function (err, docs) {
  20. // docs is [{ planet: 'Mars', system: 'solar', _id: 'id1' }]
  21. });
  22. // Project on a nested document
  23. db.findOne({ planet: 'Earth' }).projection({ planet: 1, 'humans.genders': 1 }).exec(function (err, doc) {
  24. // doc is { planet: 'Earth', _id: 'id2', humans: { genders: 2 } }
  25. });