Use-Case

The graph database use-case we are stepping through in this post is the following: In our web application we have several places where a user is led through a survey, where she decides on details for one of our products. Some of the options within the survey depend on previous decisions and some are independent.

Examples:

  • Configure a new car
  • Configure a new laptop
  • Book extras with your flight (meal, reserve seat etc.)
  • Configure a new complete kitchen
  • Collect customer feedback via logic-jump surveys


We would like to easily offer a generic page which can be seeded with any decision-tree and just plays the Q&A game with the user. We also want to be able to easily create new and modify existing decision trees in case the products change.

Graph Database Data Model

When speaking of trees it directly pops into my mind that a graph database probably is a good solution to store the data in, well every tree is a graph. So in this case the data model is actually pretty simple: First we have questions we would like to ask the user. These questions are modeled as vertices having an attribute query stating the string that should be displayed to the user. In case of a localized application we will not have one query attribute, but one for every language we support (e.g. en, de, jp etc.), for simplicity we now assume our shop is only available in English.

Attached to each question we have a list of possible answers leading the user to the next question, or to the end of the survey. These answers are best realized as the edges connecting everything together. Each answer has again a text attribute that should be presented to the user. Finally we have products which best fit for a user after undergoing the survey.

Let’s now visualize a simple decision tree. We are in an online Avocado Shop and want to give our customer the best Avocado:

survey-in-a-graph-database-arangodb

Tips and Tricks

If we set up the surveys using a graph all vertices in the graph can be reused in several surveys.

This is especially important if you want to offer the same product in completely different surveys. You do not have to store the product twice, making it easier to update. It is also important if you have overlapping surveys, say for two surveys the starting point is different, but based on some decisions the user will end up in the same dialog for both surveys and can only reach identical products with identical questions.

An example for this is if you are selling and leasing cars to a user. You at first have two sub different dialogs asking the user for selling respectively leasing conditions, but at some point in both dialogs the user finally has to decide on the car. This car selection process is again identical for both surveys.

UI

Sorry I am no UX designer 😉 In general I would require only two API endpoints:

  • showQuestion/:id Which would enter the survey at any point and return the question with it’s set of possible answers (the number of answers at this point is unknown and my UI widget is able to display an arbitrary number of option boxes).
  • showProduct/:id Which will show the product because the user is at the end of her survey.

If I want to hold some user state the UI part is responsible for it, it can for instance maintain a list of questions the user has visited and if the user presses “back” it can just resend showQuestion/:id with the second to last question.

Queries

In the first endpoints we need to return a query and all it’s possible answers. Using the data model design from above this means we have to select one question by it’s _id and all its outgoing edges.

In ArangoDB the query to achieve this is the following (including comments):

For the other endpoint we only have to display the product by its id.
This can be done via the following even simpler query:

Creating an API out of it

ArangoDB also offers a nice little framework called Foxx. This framework can easily wrap both queries into nice API endpoints by only adding a couple of lines of JS to it.
In this example we will use the nice shorthand notations that are offered by ES6.

And there we go.

See it in action

Luckily Foxx can also serve static files, which can contain HTML and JS code. This feature is useful if you want to ship a small administration frontend with you Foxx App.

In this post I will misuse it to ship my entire survey-demo widget with it. You can simply install it from github using the following repository: https://github.com/arangodb-foxx/survey-generator

Have fun trying it out or even enhance it for your Product if you like it. It is all Apache 2 Licence (and so is ArangoDB).