An example of working with relations in type-arango. Please have a look at the basic example first.
Related attributes are decorated by @OneToOne or @OneToMany. The @Attribute decorator can be omitted when the attribute does not store any data. However when the same attribute has a value, it is used to look up the related entity.
Relations can either be fetched inside custom routes by using entity.related('attribute') or by simply providing the query parameter relations
on default routes.
import { Document, Entity, Entities, OneToMany, Related } from 'type-arango'
@Document() class Author extends Entity {
@Attribute()
name: string
@OneToMany(type => Book, Books => Books.author)
books: Related<Book[]>
@Attribute(type => number)
@OneToMany(type => Book)
favorites: Related<Book[]>
}
@Document() class Book extends Entity {
@Attribute()
title: string
@Attribute(type => number)
@OneToOne(type => Author)
author: Related<Author>
}
// Authors
[{
"_key": 1,
"name": "Hermann Hesse",
"favorites": [2,3]
}, ...]
// Books
[{
"_key": 1,
"title": "Steppenwolf",
"author": 1
}, ...]
@Collection(of => Author)
@Route.GET({relations:['books']})
class Authors extends Entities {}
@Collection({of: Book, relations: ['author'], routes: ['LIST']})
class Books extends Entities {}
The code above creates the collections Authors and Books. Both collections have a route (Author GET & Books LIST) and expose a single relation.
Note: it does not matter whether the routes are created by using the @Collection(options) or additional @Route.* decorators.
The relations
property of the @Collection
decorator indicates which of the available relations can be exposed by the routes. For example, the route GET authors
can optionally return all books
of the author when called with the query parameter relations=books
.
The property can be set on a collection basis (with CollectionOpt) and or for ever route by using RouteOpt.
Fetching all Books, their Authors and their favorite books:
GET ../books?relations=author,author.favorites
[
{
"_key": 1,
"title": "Steppenwolf",
"author": {
"_key": 1,
"name": "Hermann Hesse",
"favorites": [Book2, Book3] // you get the point
}
}
]
Note: Use attributes=book.name
to omit all other attributes from the response.
type-arango provides the method related
for loading related & exposed entities inside custom routes. The following example appends all authors to the books in case the client requests them by providing the query parameters relations=author
.
@Collection(of => Book)
class Books extends Entities {
@Route.GET('custom', {relations:'author'})
static GET_CUSTOM({relations}: RouteArg){
const book = Books.find(1)
return relations(book)
}
}
Virtual relations are the simplest type of relations. They don't require any information to be stored, and the attribute does not exist in the database - therefore the @Attribute
decorator is not used.
Link relations are attributes containing either a single or a list of references to the related document/s.
The values of link relations can be tuples [KEY, VALUE]
containing an additional value, which will be merged with the related document within _value
:
{
"ratings": [
[ 2, { stars: 5 } ],
[ 5, { stars: 3 } ]
]
}
// The computed value will be merged with the related document as `_value`:
{
"ratings": [
{ ...DOCUMENT(2), _value: { stars: 5 } },
{ ...DOCUMENT(5), _value: { stars: 3 } }
]
}
Note: Make sure to define the attribute
_value
and it's permissions on the related document schema, otherwise the value will be stripped.
All relations are automatically documented within the swagger docs of the ArangoDB Web Interface.