Finder methods are designed to get data from the database. The returned data isn't just a plain object, but instances of one of the defined classes. Check the next major chapter about instances for further information. But as those things are instances, you can e.g. use the just describe expanded instance methods. So, here is what you can do:
### find - Search for one specific element in the database
```js
// search for known ids
Project.findById(123).then(function(project){
// project will be an instance of Project and stores the content of the table entry
// with id 123. if such an entry is not defined you will get null
// project will be the first entry of the Projects table with the title 'aProject' || null
})
Project.findOne({
where:{title:'aProject'},
attributes:['id',['name','title']]
}).then(function(project){
// project will be the first entry of the Projects table with the title 'aProject' || null
// project.title will contain the name of the project
})
```
### findOrCreate - Search for a specific element or create it if not available
The method `findOrCreate` can be used to check if a certain element already exists in the database. If that is the case the method will result in a respective instance. If the element does not yet exist, it will be created.
Let's assume we have an empty database with a `User` model which has a `username` and a `job`.
```js
User
.findOrCreate({where:{username:'sdepold'},defaults:{job:'Technical Lead JavaScript'}})
... the existing entry will not be changed. See the `job` of the second user, and the fact that created was false.
### findAndCountAll - Search for multiple elements in the database, returns both data and total count
This is a convienience method that combines`findAll`()and `count`()(see below), this is useful when dealing with queries related to pagination where you want to retrieve data with a `limit` and `offset` but also need to know the total number of records that match the query.
The success handler will always receive an object with two properties:
*`count` - an integer, total number records (matching the where clause)
*`rows` - an array of objects, the records (matching the where clause) within the limit/offset range
```js
Project
.findAndCountAll({
where:{
title:{
$like:'foo%'
}
},
offset:10,
limit:2
})
.then(function(result){
console.log(result.count);
console.log(result.rows);
});
```
The options [object] that you pass to`findAndCountAll`()is the same as for`findAll`()(described below).
### findAll - Search for multiple elements in the database
```js
// find multiple entries
Project.findAll().then(function(projects){
// projects will be an array of all Project instances
})
// also possible:
Project.all().then(function(projects){
// projects will be an array of all Project instances
$contained:[1,2]// <@ [1, 2] (PG array contained by operator)
$any:[2,3]// ANY ARRAY[2, 3]::INTEGER (PG only)
},
status:{
$not:false,// status NOT FALSE
}
}
})
```
### Complex filtering / OR / NOT queries
It's possible to do complex where queries with multiple levels of nested AND, OR and NOT conditions. In order to do that you can use `$or`, `$and` or `$not`:
```js
Project.findOne({
where:{
name:'a project',
$or:[
{id:[1,2,3]},
{id:{$gt:10}}
]
}
})
Project.findOne({
where:{
name:'a project',
id:{
$or:[
[1,2,3],
{$gt:10}
]
}
}
})
```
Both pieces of code code will generate the following:
### Manipulating the dataset with limit, offset, order and group
To get more relevant data, you can use limit, offset, order and grouping:
```js
// limit the results of the query
Project.findAll({limit:10})
// step over the first 10 elements
Project.findAll({offset:10})
// step over the first 10 elements, and take 2
Project.findAll({offset:10,limit:2})
```
The syntax for grouping and ordering are equal, so below it is only explained with a single example for group, and the rest for order. Everything you see below can also be done for group
```js
Project.findAll({order:'title DESC'})
// yields ORDER BY title DESC
Project.findAll({group:'name'})
// yields GROUP BY name
```
Notice how in the two examples above, the string provided is inserted verbatim into the query, i.e. column names are not escaped. When you provide a string to order / group, this will always be the case. If you want to escape column names, you should provide an array of arguments, even though you only want to order / group by a single column
```js
something.findOne({
order:[
'name',
// will return `name`
'username DESC',
// will return `username DESC` -- i.e. don't do it!
Sometimes you might be expecting a massive dataset that you just want to display, without manipulation. For each row you select, Sequelize creates an instance with functions for updat, delete, get associations etc. If you have thousands of rows, this might take some time. If you only need the raw data and don't want to update anything, you can do like this to get the raw data.
```js
// Are you expecting a masssive dataset from the DB,
// and don't want to spend the time building DAOs for each entry?
// You can pass an extra query option to get the raw data instead:
Project.findAll({where:...},{raw:true})
```
### count - Count the occurences of elements in the database
There is also a method for counting database objects:
When you are retrieving data from the database there is a fair chance that you also want to get associations with the same query - this is called eager loading. The basic idea behind that, is the use of the attribute `include` when you are calling `find` or `findAll`. Lets assume the following setup:
Notice that the accessor is plural. This is because the association is many-to-something.
If an association is aliased (using the `as` option), you must specify this alias when including the model. Notice how the user's `Tool`s are aliased as `Instruments` above. In order to get that right you have to specify the model you want to load, as well as the alias:
When eager loading we can also filter the associated model using `where`. This will return all `User`s in which the `where` clause of `Tool` model matches rows.
```js
User.findAll({
include:[{
model:Tool,
as:'Instruments',
where:{name:{$like:'%ooth%'}}
}]
}).then(function(users){
console.log(JSON.stringify(users))
/*
[{
"name": "John Doe",
"id": 1,
"createdAt": "2013-03-20T20:31:45.000Z",
"updatedAt": "2013-03-20T20:31:45.000Z",
"Instruments": [{
"name": "Toothpick",
"id": 1,
"createdAt": null,
"updatedAt": null,
"UserId": 1
}]
}],
[{
"name": "John Smith",
"id": 2,
"createdAt": "2013-03-20T20:31:45.000Z",
"updatedAt": "2013-03-20T20:31:45.000Z",
"Instruments": [{
"name": "Toothpick",
"id": 1,
"createdAt": null,
"updatedAt": null,
"UserId": 1
}]
}],
*/
})
```
When an eager loaded model is filtered using `include.where` then `include.required` is implicitly set to
`true`. This means that an inner join is done returning parent models with any matching children.
### Including everything
### Including everything
To include all attributes, you can pass a single object with `all: true`:
To include all attributes, you can pass a single object with `all: true`:
...
@@ -504,6 +551,7 @@ Company.findAll({
...
@@ -504,6 +551,7 @@ Company.findAll({
### Nested eager loading
### Nested eager loading
You can use nested eager loading to load all related models of a related model:
You can use nested eager loading to load all related models of a related model:
```js
```js
User.findAll({
User.findAll({
include:[
include:[
...
@@ -534,7 +582,8 @@ User.findAll({
...
@@ -534,7 +582,8 @@ User.findAll({
*/
*/
})
})
```
```
This will produce an outer join. However, a `where` clause on a related model will create an inner join and return only the instances that have matching sub-models. To return all the instances, you should add `required: false`.
This will produce an outer join. However, a `where` clause on a related model will create an inner join and return only the instances that have matching sub-models. To return all parent instances, you should add `required: false`.
```js
```js
User.findAll({
User.findAll({
...
@@ -554,6 +603,8 @@ User.findAll({
...
@@ -554,6 +603,8 @@ User.findAll({
})
})
```
```
The query above will return all users, and all their instruments, but only those teachers associated with `Woodstock Music School`.