Getting started with ArangoDB and Symfony 2 – part 2

API, php Tags: , , , Leave a comment
This is part 2 (of 4) of an introduction to the use of ArangoDB together with Symfony 2. You’ll find the links to the other parts of this tutorial at the end of this text.

You can download the completed demo at Github.

The data structure

Our app deals with movies: each movie has a title, a year of release and it is assigned to a genre. Each movie deals with none, one or many topics.

In a relational database we would probably create a table movie and another table topic and join them with a shared movie id.

ArangoDB follows like other document stores the “aggregate model” approach: In short terms this means that you should put data that is often needed together into one document. Remember: documents are a bit like rows in the relation world; in nosql world they can have a nested structure.


So our movie entity looks like this in JSON notation:

{
    "released": 1983,
    "genre": "sci-fi",
    "title": "Star wars",
    "topics": ["spaceship", "laser-games", "romance"]
}

A remark for those who are not familiar with nosql databases yet: One of the advantages of document stores is the great flexibility of the data model. There could be movies in ArangoDB having 20 topics or no topics at all. There could also be some records for which additional information were provided like if there is a director’s cut available or not. Just add and remove attributes, as you need them. This is especially nice for prototyping or persisting objects which occur in many, slightly different versions like cars or clothing.

Accessing our data in Symfony

ArangoDB returns JSON, but we won’t see raw JSON in Symfony necessarily. The ArangoDB driver maps the JSON documents to instances of ArangoDbDocument automatically. We can access the properties of our movie documents with get and set methods:

$movie->get(“title”); // string(9) "Star Wars"
$movie->get(“topics”); // array(3)

Of course we can also extend ArangoDBDocument to create a more specialized movie entity class. We’ll see that later on when we have a look at our CRUD code.

ArangoDB and the PHP driver for ArangoDB offer “simple queries” for basic operations like “get document by id” or “get all movies with attribute = ‘foo’”. This becomes messy for joins and more complex conditions. Therefore ArangoDB also supports a full-blown query language (AQL).

And yes, we are hearing you asking: Why the heck did they invent a new query language, SQL is great, isn’t it? The main reason for developing our own query language was that ArangoDB offers lots of functionality which is not covered by the SQL language standard: you can’t express graph relations, there is no proper support for lists and so on.

The first feature: Listing movies using the simple query API

Our movie database should be able to list movies. To make it at least a little bit more interesting the list is split by genre. The genre is set via GET parameter from the user interface.

We are using ArangoDB’s simple query API for this feature. This API has a method “byExample” which will return all documents with the same characteristics as the given example document. The method returns a cursor which we’ll pass to the Twig template.

// src/Triagens/ArangodbBundle/Controller/DefaultController.php
use triagens\ArangoDb\Document;
use triagens\ArangoDb\CollectionHandler as CollectionHandler;
/**
* @Route("/list/{genre}", defaults={"genre" = "sci-fi"})
* @Template
*/
public function listAction($genre) {
    // get connection to ArangoDB
    $connection = $this->get('mop_arangodb.default_connection');
    $collectionHandler = new CollectionHandler($connection);
 
    // create example document which is used for the search by example afterwards
    $movie = new Document();
    $movie->set("genre", $genre);
 
    $cursor = $collectionHandler->byExample(“movies”,$movie);
    return array(
    'movies' => $cursor->getAll()
    );
}

The Twig part is pretty straight forward as well. Note how you can access the movie’s attributes and in line 7 that “topics” is an array you can iterate through.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Triagens/ArangodbBundle/Resources/views/list.html.twig
{% if movies|length > 0 %}
    {% for movie in movies %}
 
        <h1>{{movie.get("title")}}</h1>
 
        {% for topic in movie.get("topics") %}
            - {{topic}} <br>
        {% endfor %}
 
    {% endfor %}
 
{% else %}
    No movies found.
{% endif %}

The end

Congrats, you have reached the end of part 2 the tutorial. There is more:

Dorthe Lübbert

About Dorthe Lübbert

web developer from Cologne, interested in alternative databases & member of the ArangoDB team - mainly helping out with website and community related stuff.