# 5. The Data Model

The Data Model defines the structure of the database that will be used by your app, and should be determined by the nature and structure of the data that is to be accessed and used in the app. JourneyApps supports fully relational data models:

* You define the `Models` that are required in the app
* For each model you define various `Fields`, each with a specific `type` (for example a `name` field of type `text` to store the *Name* of the object, or a `created_at` field of type `datetime` to store the exact date and time the object was created)
* You also define the `Relationships` between Models, which are used to link related models (for example a one-to-many relationship between *cart* and *item*, i.e. a *cart* can have many *items* linked to it)
* You can also define special fields for `default display` values, `app indexes`, and for configuring `webhooks`

These then describe the structure and nature of data that can be stored in each model. An instance of a model is called an `object`, and each `object` has a unique, system generated, identifier called the `id` of the `object`.

{% hint style="success" %}
**Learn more about relational databases**

Understanding the basics of relational databases will simplify the design of your app's data model significantly. If you are not familiar with relational databases, we suggest that you read more about them using online resources.
{% endhint %}

### Single, Common Data Model

A valuable feature of JourneyApps is that the Data Model for an app only needs to be defined **once**, in OXIDE, and is then used throughout the entire JourneyApps Cloud. Once you've defined your Data Model it will be used by the application, the Backend, the API and all other related JourneyApps services.

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2FGnWKLrV15gOSPRyHZOHV%2Farchitecture-diagram-app-backend-data-model.jpg?alt=media\&token=8f8270b7-b364-4876-8a84-f538142710d6)

### Syntax

This is an example of a Data Model for a simple asset management app. It contains two models, `asset` and `building`. Most of the data collected are for the `assets`, and a `building` can have many `assets` - a one-to-many relationship.

For details, see [Data Model Configuration](https://docs.journeyapps.com/reference/build/data-model-configuration).

{% code title="schema.xml" %}

```xml
<data-model>
  <model name="asset" label="Asset">
    <field name="make" label="Make" type="text:name"/>
    <field name="model" label="Model" type="text:name"/>
    <field name="serial_number" label="Serial Number" type="text:number"/>
    <field name="description" label="Description" type="text"/>
    <field name="picture" label="Picture" type="photo"/>
    <field name="condition" label="Condition" type="single-choice">
      <option key="good">Good</option>
      <option key="ok">Ok</option>
      <option key="bad">Bad</option>
    </field>

    <belongs-to model="building"/>

    <display>{make} {model} {serial_number}</display>
  </model>

  <model name="building" label="Building">
    <field name="name" label="Name" type="text:name"/>

    <has-many model="asset" name="assets"/>

    <display>{name}</display>
  </model>
</data-model>
```

{% endcode %}

### A Real-World Example

We mentioned that we'll use a real-world example of an app throughout the tutorial, and you saw in the [JourneyApps Approach to Building Apps section on the *What is JourneyApps?*](https://docs.journeyapps.com/reference/readme#the-journeyapps-approach-to-building-apps) page that the Data Model is the best place to start when you build an app on JourneyApps. So let's introduce our real-world example app and then build the Data Model for it:

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-b76155886717a77b8a3028970a25df8088f9c12d%2Fsnag-list-user-photo.jpg?alt=media)

{% hint style="info" %}
**Real-World Example: Construction Punch List**

In the construction and real estate industries, a "punch list" is often created to keep inventory of the things that an owner or tenant isn't happy with when a building project is finished or when they move into a new leased building.

Things that could appear on a punch list include: Cracks in ceiling and walls, skirting boards that aren't properly affixed, uneven or unfinished drywall, crooked fixtures, loose wiring, poor insulation, leaking pipes, etc.

A great alternative to compiling and maintaining a punch list manually is to build a mobile app on JourneyApps that allows capturing and centralized tracking of punch list items electronically. Photos, notes and GPS locations can easily be attached to each item, and it is easy to export the punch list and send it to someone, or to build a web portal that pulls data from to the JourneyApps API where stakeholders can browse the punch list.
{% endhint %}

### Create the punch List App & Link Test Device

We will now create a new blank app to start building the punch List app.

**Important: Start Again with a New App.**

Navigate to the OXIDE Dashboard (top left corner) and repeat the instructions in [Section 2: Creating a New App](https://docs.journeyapps.com/reference/get-started/tutorial-build-your-first-app/2.-creating-a-new-app) to create a new app named **"Punch List"**, and then link your mobile device to that app using the **Test App** action.

### Open up the Data Model Workspace

After creating the new **Punch List** app, go to the **Data Model** Workspace. You should see the following:

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-3882e1221a6a1f0b806c70b4399fc5d5b6735586%2Foxide-pl-data-model.png?alt=media)

What you are seeing is your data model `xml` code, also called the `schema`, in the right editor pane, the ERD for your current data model rendered in the left editor pane, and the Data Model panel on the left of the screen. Notice that any new JourneyApps application that you create starts with two models in the Data Model, `user` and `push_notification`. The `user` model is used to store information about the end users of your app and is required for most apps. By default, the `user` model has one field, `name`, of type `text` which stores the user's name. The default `push_notification` model is used and pre-configured to allow you to easily create and send **Push Notifications** to your app users, but more about that at a later stage.

Your `schema.xml` file should contain the following:

{% code title="schema.xml" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<data-model>
    <!-- Do not remove this - it is used to store information about your app's users: -->
    <model name="user" label="User">
        <field name="name" label="Name" type="text:name"/>

        <display>{name}</display>
    </model>

    <!-- Used for Push Notifications - to send a push notification, create a 'push_notification' object -->
    <!--                               and specify the recipient in the 'belongs to user' relationship -->
    <!-- For more details, refer to: http://resources.journeyapps.com/v4/push-notifications -->
    <model name="push_notification" label="Push Notification">
        <field name="message" label="Message" type="text" />
        <field name="received_at" label="Received At" type="datetime" />
        <field name="created_at" label="Created At" type="datetime" />

        <belongs-to model="user" />
        <display>{message} ({user})</display>
        <notify-user message="{message}" received-field="received_at" recipient-field="user"/>
    </model>

    <!-- ADD MODELS HERE: -->

</data-model>
```

{% endcode %}

Whenever you modify your Data Model XML code (the `schema.xml` file), the ERD will be updated automatically.

### Building the Data Model

Let's look at what the requirements are for our Punch List app's Data Model

**App Design: Construction Punch List.** The simplest Data Model for our Punch List App is to have a collection of punch list items, each with a photo, comments and status (Open/Closed). Our app will then allow users to capture new punch list items that are initially "Open", which they can then later change to "Closed" when the punch has been taken care of.

### Add a Model

Therefore, we need to add a new model to our Data Model named *item*. Below *"ADD MODELS HERE"* in the XML, type `model` and you should see an auto-complete suggestion underneath your cursor. Insert the auto-complete suggestion by pressing *return/enter* (If there is only one auto-complete suggestion it will be selected by default and so there is no need to select it first). If you do not see the auto-complete suggestion, or you have clicked-away from it, simply get your cursor back to the end of the word you were typing and press `Ctrl` + `spacebar`.

For our newly added model, enter *item* as the name of the model, and *Item* as the label (the `name=""` attribute is what is used to refer to the model in your code, whereas the `label=""` attribute is a human-readable label for the model that is used in other parts of the platform).

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-3c7b82cd09cab4e5481a27ecb3b559193d3096e2%2Foxide-pl-dm-model-ac.png?alt=media)

```xml
<model name="item" label="Item">
    <field name="" label="" type="" />

    <display></display>
</model>
```

### Add Some Fields to the Object Type

Now populate your first data model field, *comments*, and specify its type as `text`.

```xml
<model name="item" label="Item">
    <field name="comments" label="Comments" type="text" />
  
    <display></display>
</model> 
```

Next we want to add an attribute to store the photo of the punch list item. Type `photo` on the next line and once you see the auto-complete suggestion for a *photo field* hit *return/enter* to insert. This will give you a field for a photo and now you just need to add the name and the label. Fill in *photo* as the name and *Photo* as the label.

```xml
<model name="item" label="Item">
    <field name="comments" label="Comments" type="text" />
    <field name="photo" label="Photo" type="photo" />

    <display></display>
</model>
```

To add our last field for the "status" of our punch list item, we'll use the *single-choice* type — which is used to create a fixed "list" of values that a specific field can contain). (A full guide to all the possible field types in JourneyApps can be found [here](https://docs.journeyapps.com/reference/build/data-model-configuration/model/field).) Type `single-choice` on the next line and insert the auto-complete suggestion for the *single-choice field*, not the *single-choice-integer field*, and fill in *status* for the name and *Status* for the label. To populate and specify the list of options that this field can contain you need to list `<option>` tags inside the *single-choice* field. Therefore, set the contents of those tags to *Open* and *Closed.*

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-3cb0e16cfc103a12287dc9be19f4d29de4eb88ab%2Foxide-pl-dm-single-choice-ac.png?alt=media)

{% hint style="info" %}
**Pro Tip: Jump between \_XML**\_\*\* input fields\*\*

You can use Ctrl + . and Ctrl + , to move your cursor to the next and previous input fields in any *xml* code in JourneyApps. Try it now in your Data Model (*schema.xml*)
{% endhint %}

```xml
<model name="item" label="Item">
    <field name="comments" label="Comments" type="text" />
    <field name="photo" label="Photo" type="photo" />
    <field name="status" label="Status" type="single-choice">
        <option key="Open">Open</option>
        <option key="Closed">Closed</option>
    </field>
    <display></display>
</model>
```

### Display Format

The last thing we need to customize is how our `item` objects will be displayed by default (e.g. when they are shown in a list). This is specified using the `<display></display>` tag that you can see below your fields. Inside the `display` tags we can make use of **String interpolation**. In `xml` *string interpolation* of variables/placeholders is accomplished using curly brackets. So, here you can specify which field values should be included when the object is displayed. Field names are wrapped in curly brackets, and you can also include some raw text. Let's make our punch List items display their *Status*, followed by a hyphen and then their *Comments*:

```xml
<display>{status} - {comments}</display>
```

You can learn more about `xml` format strings / string interpolation in detail in [this section](https://docs.journeyapps.com/reference/app-features/xml-format-strings) of the reference documentation.

### That's It!

We've now created the first version of the Data Model for our Punch List app. This will now automatically be used to determine the structure of the "database" in your app and elsewhere throughout the JourneyApps ecosystem (e.g. for storing your app's data in the cloud, exposing that data through the backend API, etc.).

At this time your Data Model (`schema.xml`) should like like this.

{% code title="schema.xml" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<data-model>
    <!-- Do not remove this - it is used to store information about your app's users: -->
    <model name="user" label="User">
        <field name="name" label="Name" type="text:name"/>

        <display>{name}</display>
    </model>

    <!-- Used for Push Notifications - to send a push notification, create a 'push_notification' object -->
    <!--                               and specify the recipient in the 'belongs to user' relationship -->
    <!-- For more details, refer to: http://resources.journeyapps.com/v4/push-notifications -->
    <model name="push_notification" label="Push Notification">
        <field name="message" label="Message" type="text" />
        <field name="received_at" label="Received At" type="datetime" />
        <field name="created_at" label="Created At" type="datetime" />

        <belongs-to model="user" />
        <display>{message} ({user})</display>
        <notify-user message="{message}" received-field="received_at" recipient-field="user"/>
    </model>

    <!-- ADD MODELS HERE: -->
    <model name="item" label="Item">
        <field name="comments" label="Comments" type="text" />
        <field name="photo" label="Photo" type="photo" />
        <field name="status" label="Status" type="single-choice">
            <option key="Open">Open</option>
            <option key="Closed">Closed</option>
        </field>
        
        <display>{status} - {comments}</display>
    </model>    

</data-model>
```

{% endcode %}
