1
0
Fork 0
arangodb/Documentation/Books/Users/Foxx/Develop/Repository.mdpp

607 lines
13 KiB
Plaintext

!CHAPTER Details on FoxxRepository
A repository is a gateway to the database. It gets data from the database, updates it or saves new data. It uses the given model when it returns a model and expects instances of the model for methods like save. In your repository file, export the repository as **repository**.
```javascript
var Foxx = require("@arangodb/foxx");
class TodosRepository extends Foxx.Repository {
// ...
}
exports.repository = TodosRepository;
```
The following events are emitted by a repository:
- beforeCreate
- afterCreate
- beforeSave
- afterSave
- beforeUpdate
- afterUpdate
- beforeRemove
- afterRemove
Model lifecycle:
```js
var person = new PersonModel();
person.on('beforeCreate', function() {
this.fancyMethod(); // Do something fancy with the model
});
var people = new Repository(appContext.collection("people"), { model: PersonModel });
people.save(person);
// beforeCreate(person)
// beforeSave(person)
// The model is created at db
// afterSave(person)
// afterCreate(person)
people.update(person, data);
// beforeUpdate(person, data)
// beforeSave(person, data)
// The model is updated at db
// afterSave(person, data)
// afterUpdate(person, data)
people.remove(person);
// beforeRemove(person)
// The model is deleted at db
// afterRemove(person)
```
!SUBSECTION Initialize
`new FoxxRepository(collection, opts)`
Create a new instance of Repository.
A Foxx Repository is always initialized with a collection object. You can get
your collection object by asking your Foxx.Controller for it: the
*collection* method takes the name of the collection (and will prepend
the prefix of your application). It also takes two optional arguments:
1. Model: The prototype of a model. If you do not provide it, it will default
to Foxx.Model
2. Prefix: You can provide the prefix of the application if you need it in
your Repository (for some AQL queries probably)
If the Model has any static methods named after the lifecycle events, they
will automatically be registered as listeners to the events emitted by this
repository.
**Examples**
```js
instance = new Repository(appContext.collection("my_collection"));
or:
instance = new Repository(appContext.collection("my_collection"), {
model: MyModelPrototype
});
```
Example with listeners:
```js
var ValidatedModel = Model.extend({
schema: {...}
}, {
beforeSave(modelInstance) {
if (!modelInstance.valid) {
throw new Error('Refusing to save: model is not valid!');
}
}
});
instance = new Repository(collection, {model: ValidatedModel});
```
!SECTION Defining custom queries
You can define custom query methods using Foxx.createQuery and Foxx.Repository.extend.
For more details see the chapter on [Foxx Queries](../Develop/Queries.md).
**Examples**
Making a simple query in the repository and using it from the controller:
```js
// in the repository
var Foxx = require("@arangodb/foxx");
class TodosRepository extends Foxx.Repository {
// ...
});
TodosRepository.prototype.getPendingItems = Foxx.createQuery(
'FOR todo IN my_todos FILTER todo.completed == false RETURN todo'
);
// in the controller
ctrl.get("/", function(req, res) {
req.json(todosRepository.getPendingItems());
});
```
It is also possible to supply parameters to the query:
```js
// in the repository
TodosRepository.prototype.getPendingItemById = Foxx.createQuery({
query: 'FOR todo IN my_todos FILTER todo.completed == false FILTER todo._key == @id RETURN todo',
params: ['id']
});
// in the controller
ctrl.get("/:id", function(req, res) {
var id = req.params("id");
var rv = todosRepository.getPendingItemById(id);
res.json(rv);
});
```
The list of results can also be transformed before returning it from the repository:
```js
// in the repository
TodosRepository.prototype.getPendingItemById = Foxx.createQuery({
query: 'FOR todo IN my_todos FILTER todo.completed == false FILTER todo._key == @id RETURN todo',
params: ['id'],
transform: function(results, extra) {
for (var i = 0; i < results.length; i++) {
results[i].extraProperty = extra;
}
}
});
// in the controller
ctrl.get("/:id", function(req, res) {
var id = req.params("id");
var extra = req.params("extra");
var rv = todosRepository.getPendingItemById(id, extra);
res.json(rv);
});
```
!SECTION Attributes of a Repository
!SUBSECTION Collection
The wrapped ArangoDB collection object.
!SUBSECTION Model
The model of this repository. Formerly called "modelPrototype".
!SUBSECTION Model schema
The schema of this repository's model.
!SUBSECTION Prefix
The prefix of the application. This is useful if you want to construct AQL
queries for example.
!SECTION Defining indexes
Repository can take care of ensuring the existence of collection indexes for you.
If you define indexes for a repository, instances of the repository will have
access to additional index-specific methods like **range** or **fulltext** (see below).
The syntax for defining indexes is the same used in [*collection.ensureIndex*](../../IndexHandling/README.md).
**Examples**
```js
var Foxx = require('@arangodb/foxx');
class FulltextRepository extends Foxx.Repository {
// ...
}
FulltextRepository.prototype.indexes = [
{
type: 'fulltext',
fields: ['text'],
minLength: 3
}
];
```
!SECTION Methods of a Repository
!SUBSECTION Adding entries to the repository
`FoxxRepository#save(model)`
Saves a model into the database.
Expects a model. Will set the ID and Rev on the model.
Returns the model.
@EXAMPLES
```javascript
repository.save(my_model);
```
!SUBSECTION Finding entries in the repository
`FoxxRepository#byId(id)`
Returns the model for the given ID ("collection/key") or "key".
@EXAMPLES
```javascript
var byIdModel = repository.byId('test/12411');
byIdModel.get('name');
var byKeyModel = repository.byId('12412');
byKeyModel.get('name');
```
`FoxxRepository#byExample(example)`
Returns an array of models for the given ID.
@EXAMPLES
```javascript
var myModel = repository.byExample({ amazing: true });
myModel[0].get('name');
```
`FoxxRepository#firstExample(example)`
Returns the first model that matches the given example.
@EXAMPLES
```javascript
var myModel = repository.firstExample({ amazing: true });
myModel.get('name');
```
`FoxxRepository#all()`
Returns an array of models that matches the given example. You can provide
both a skip and a limit value.
**Warning:** ArangoDB doesn't guarantee a specific order in this case, to make
this really useful we have to explicitly provide something to order by.
*Parameter*
* *options* (optional):
* *skip* (optional): skips the first given number of models.
* *limit* (optional): only returns at most the given number of models.
@EXAMPLES
```javascript
var myModel = repository.all({ skip: 4, limit: 2 });
myModel[0].get('name');
```
`FoxxRepository#any()`
Returns a random model from this repository (or null if there is none).
@EXAMPLES
```javascript
repository.any();
```
!SUBSECTION Removing entries from the repository
`FoxxRepository#remove(model)`
Remove the model from the repository.
Expects a model.
@EXAMPLES
```javascript
repository.remove(myModel);
```
`FoxxRepository#removeById(id)`
Remove the document with the given ID ("collection/key") or "key".
Expects an ID or key of an existing document.
@EXAMPLES
```javascript
repository.removeById('test/12121');
repository.removeById('12122');
```
`FoxxRepository#removeByExample(example)`
Find all documents that fit this example and remove them.
@EXAMPLES
```javascript
repository.removeByExample({ toBeDeleted: true });
```
!SUBSECTION Replacing entries in the repository
`FoxxRepository#replace(model)`
Find the model in the database by its *_id* and replace it with this version.
Expects a model. Sets the revision of the model.
Returns the model.
@EXAMPLES
```javascript
myModel.set('name', 'Jan Steemann');
repository.replace(myModel);
```
`FoxxRepository#replaceById(id, object)`
Find the item in the database by the given ID ("collection/key") or "key"
and replace it with the given object's attributes.
If the object is a model, updates the model's revision and returns the model.
@EXAMPLES
```javascript
repository.replaceById('test/123345', myNewModel);
repository.replaceById('123346', myNewModel);
```
`FoxxRepository#replaceByExample(example, object)`
Find every matching item by example and replace it with the attributes in
the provided object.
@EXAMPLES
```javascript
repository.replaceByExample({ replaceMe: true }, myNewModel);
```
!SUBSECTION Updating entries in the repository
`FoxxRepository#update(model, object)`
Find the model in the database by its *_id* and update it with the given object.
Expects a model. Sets the revision of the model and updates its properties.
Returns the model.
@EXAMPLES
```javascript
repository.update(myModel, {name: 'Jan Steeman'});
```
`FoxxRepository#updateById(id, object)`
Find an item by ID ("collection/key") or "key" and update it with the
attributes in the provided object.
If the object is a model, updates the model's revision and returns the model.
@EXAMPLES
```javascript
repository.updateById('test/12131', { newAttribute: 'awesome' });
repository.updateById('12132', { newAttribute: 'awesomer' });
```
`FoxxRepository#updateByExample(example, object)`
Find every matching item by example and update it with the attributes in
the provided object.
@EXAMPLES
```javascript
repository.updateByExample({ findMe: true }, { newAttribute: 'awesome' });
```
`FoxxRepository#exists(id)`
Checks whether a model with the given ID or key exists.
@EXAMPLES
```javascript
repository.exists(model.get('_id'));
```
!SUBSECTION Counting entries in the repository
`FoxxRepository#count()`
Returns the number of entries in this collection.
@EXAMPLES
```javascript
repository.count();
```
!SUBSECTION Index-specific repository methods
`FoxxRepository#range(attribute, left, right)`
Returns all models in the repository such that the attribute is greater
than or equal to *left* and strictly less than *right*.
For range queries it is required that a skiplist index is present for the
queried attribute. If no skiplist index is present on the attribute, the
method will not be available.
*Parameter*
* *attribute*: attribute to query.
* *left*: lower bound of the value range (inclusive).
* *right*: upper bound of the value range (exclusive).
@EXAMPLES
```javascript
repository.range("age", 10, 13);
```
`FoxxRepository#near(latitude, longitude, options)`
Finds models near the coordinate *(latitude, longitude)*. The returned
list is sorted by distance with the nearest model coming first.
For geo queries it is required that a geo index is present in the
repository. If no geo index is present, the methods will not be available.
*Parameter*
* *latitude*: latitude of the coordinate.
* *longitude*: longitude of the coordinate.
* *options* (optional):
* *geo* (optional): name of the specific geo index to use.
* *distance* (optional): If set to a truthy value, the returned models
will have an additional property containing the distance between the
given coordinate and the model. If the value is a string, that value
will be used as the property name, otherwise the name defaults to *"distance"*.
* *limit* (optional): number of models to return. Defaults to *100*.
@EXAMPLES
```javascript
repository.near(0, 0, {geo: "home", distance: true, limit: 10});
```
`FoxxRepository#within(latitude, longitude, radius, options)`
Finds models within the distance *radius* from the coordinate
*(latitude, longitude)*. The returned list is sorted by distance with the
nearest model coming first.
For geo queries it is required that a geo index is present in the
repository. If no geo index is present, the methods will not be available.
*Parameter*
* *latitude*: latitude of the coordinate.
* *longitude*: longitude of the coordinate.
* *radius*: maximum distance from the coordinate.
* *options* (optional):
* *geo* (optional): name of the specific geo index to use.
* *distance* (optional): If set to a truthy value, the returned models
will have an additional property containing the distance between the
given coordinate and the model. If the value is a string, that value
will be used as the property name, otherwise the name defaults to *"distance"*.
* *limit* (optional): number of models to return. Defaults to *100*.
@EXAMPLES
```javascript
repository.within(0, 0, 2000 * 1000, {geo: "home", distance: true, limit: 10});
```
`FoxxRepository#fulltext(attribute, query, options)`
Returns all models whose attribute *attribute* matches the search query
*query*.
In order to use the fulltext method, a fulltext index must be defined on
the repository. If multiple fulltext indexes are defined on the repository
for the attribute, the most capable one will be selected.
If no fulltext index is present, the method will not be available.
*Parameter*
* *attribute*: model attribute to perform a search on.
* *query*: query to match the attribute against.
* *options* (optional):
* *limit* (optional): number of models to return. Defaults to all.
@EXAMPLES
```javascript
repository.fulltext("text", "word", {limit: 1});
```