mirror of https://gitee.com/bigwinds/arangodb
607 lines
13 KiB
Plaintext
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});
|
|
```
|
|
|