!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}); ```