241 lines
5.6 KiB
Markdown
241 lines
5.6 KiB
Markdown
---
|
|
tags:
|
|
- mongo-db
|
|
- node-js
|
|
- mongoose
|
|
- databases
|
|
---
|
|
|
|
# Query a Mongo collection with Mongoose
|
|
|
|
We now have the following entries in our `courses` collection:
|
|
|
|
```js
|
|
{
|
|
name: 'Python Course',
|
|
author: 'Terry Ogleton',
|
|
tags: [ 'python', 'backend' ],
|
|
isPublished: true,
|
|
_id: new ObjectId("62f4e2527ac4aa2c30d41d23"),
|
|
date: 2022-08-11T11:04:50.750Z,
|
|
__v: 0
|
|
}
|
|
|
|
{
|
|
name: 'Javascript Course',
|
|
author: 'Tosh Gnomay',
|
|
tags: [ 'js', 'frontend' ],
|
|
isPublished: true,
|
|
_id: new ObjectId("62f4e2527ac4aa2c30d41d24"),
|
|
date: 2022-08-11T11:04:50.750Z,
|
|
__v: 0
|
|
}
|
|
|
|
```
|
|
|
|
Now we will query the collection. This capability is provided via the Mongoose
|
|
schema class we used to create the `Course`
|
|
[model](Create_collections_and_documents_with_Mongoose.md#models).
|
|
We have the following methods available to use from the schema:
|
|
|
|
- `find`
|
|
- `findById`
|
|
- `findByIdAndRemove`
|
|
- `findByIdAndUpdate`
|
|
- `findOne`
|
|
- `findOneAndUpdate`
|
|
- `findOneAndRemove`
|
|
- ...
|
|
|
|
The various `find` methods return a value that is promisified.
|
|
|
|
## Return values with `find`
|
|
|
|
```js
|
|
async function getCourses() {
|
|
const courses = await Course.find();
|
|
console.log(courses);
|
|
}
|
|
```
|
|
|
|
## Filter values returned
|
|
|
|
This will return all the published courses where Tosh Gnomay is the author:
|
|
|
|
```js
|
|
async function getCourses() {
|
|
const courses = await Course.find({
|
|
author: "Tosh Gnomay",
|
|
isPublished: true,
|
|
});
|
|
console.log(courses);
|
|
}
|
|
```
|
|
|
|
This time we will filter by the same author but we will add additional
|
|
parameters to distinguish:
|
|
|
|
- only the first ten entries (using `.limit(10)`)
|
|
- sort ascending by name (using `.sort({name: 1}))` , to descend we would use
|
|
`-1`)
|
|
- only return the properties `name` and `tags` for the item in the collection
|
|
(using `.select({name: 1, tags: 1})`)
|
|
|
|
```js
|
|
async function getCourses() {
|
|
const courses = await Course.find({
|
|
author: "Tosh Gnomay",
|
|
isPublished: true,
|
|
})
|
|
.limit(10)
|
|
.sort({ name: 1 })
|
|
.select({ name: 1, tags: 1 });
|
|
console.log(courses);
|
|
}
|
|
```
|
|
|
|
This returns:
|
|
|
|
```js
|
|
[
|
|
{
|
|
_id: new ObjectId("62f4f07a875cff48827b8731"),
|
|
name: "Java Course",
|
|
tags: ["java", "backend"],
|
|
},
|
|
{
|
|
_id: new ObjectId("62f4e2527ac4aa2c30d41d24"),
|
|
name: "Javascript Course",
|
|
tags: ["js", "frontend"],
|
|
},
|
|
];
|
|
```
|
|
|
|
> Note that the UUID is always returned, whether we specify it or not.
|
|
|
|
## Querying with operators
|
|
|
|
So far when filtering we have been doing so with reference to properties that
|
|
exist on the document's model (`author`, `isPublished` etc) and we have applied
|
|
tranformations on the data returned (sorting, limiting the number or matches
|
|
etc.). However we can also apply **operators** within our queries. Operators
|
|
allow us to perform computations on the data, for example: for a given numerical
|
|
property on an object, return the objects for which this value is within a
|
|
certain range.
|
|
|
|
When we apply operators we use the `$` symbol before the operator and pass the
|
|
operator function as an object.
|
|
|
|
The schema:
|
|
|
|
```
|
|
Model.find( { property: { $operator: conditions } } )
|
|
```
|
|
|
|
### Comparison operators
|
|
|
|
The following comparison operators are available in MongoDB:
|
|
|
|
| Operator | Function |
|
|
| -------- | ------------------------- |
|
|
| `eq` | Equal to |
|
|
| `ne` | Not equal to |
|
|
| `gt` | Greater than |
|
|
| `gte` | Greater than or less than |
|
|
| `lt` | Less than |
|
|
| `lte` | Less than or equal to |
|
|
| `in` | In |
|
|
| `nin` | Not in |
|
|
|
|
We can employ these comparators within a `.find` filter. For example let's
|
|
imagine that our `courses` instances have a property of `price`.
|
|
|
|
To filter course prices that are greater than or equal to 10 and less than or
|
|
equal to 29:
|
|
|
|
```js
|
|
Course.find({ price: { $gte: 10, $lte: 20 } });
|
|
```
|
|
|
|
To filter course prices that are either 10, 15 or 20:
|
|
|
|
```js
|
|
Course.find({ price: { $in: [10, 15, 20] } });
|
|
```
|
|
|
|
### Logical operators
|
|
|
|
When we apply logical operators, we do not apply the query within the main
|
|
`find` method. We use a dedicated method that corresponds to the logical
|
|
predicate.
|
|
|
|
For example to query by logical
|
|
[OR](Truth-functional_connectives.md#disjunction):
|
|
|
|
```js
|
|
async function getCourses() {
|
|
const courses = await Course.find().or([
|
|
{ author: "Tosh Gnomay" },
|
|
{ isPublished: true },
|
|
]);
|
|
console.log(courses);
|
|
}
|
|
```
|
|
|
|
We write each disjunct as an object representing the conditions we are filtering
|
|
for within an array that is passed to the `.or()` method.
|
|
|
|
The same syntax applies for conjunction.
|
|
|
|
### Regular expressions
|
|
|
|
When filtering by strings we can use Regex for greater power.
|
|
|
|
Previously we filtered by the author name:
|
|
|
|
```js
|
|
.find({author: "Tosh Gnomay"})
|
|
```
|
|
|
|
To demonstrate regex we could filter by names beginning with `T`:
|
|
|
|
```js
|
|
.find({author: /^T*/})
|
|
```
|
|
|
|
```js
|
|
async function getCourses() {
|
|
const courses = await Course.find()
|
|
.or([{ author: "Tosh Gnomay" }, { isPublished: true }])
|
|
.count();
|
|
console.log(courses);
|
|
}
|
|
```
|
|
|
|
This will return a number.
|
|
|
|
### Pagination
|
|
|
|
We previously used the `limit()` method to control how many matches we return
|
|
from a query. We can extend this functionality by creating pagination. This
|
|
allows us to meter the return values into set chunks. This is used frequently
|
|
when interacting with a database through a mediating RESTful API. For example to
|
|
return values from endpoints such as:
|
|
|
|
```
|
|
/api/courses?pageNumber=2&pageSize=10
|
|
```
|
|
|
|
To do this you pass two values as query parameters
|
|
|
|
```js
|
|
const pageNumber = 2;
|
|
const pageSize = 10;
|
|
|
|
async function getCourses() {
|
|
const courses = await Course.find()
|
|
.skip(pageNumber - 1 * pageSize)
|
|
.limit(pageSize);
|
|
console.log(courses);
|
|
}
|
|
```
|