Database Integrations

Jovo offers a variety of integrations that allow you to store elements like user data, session data, and a user's interaction history in a database.

Introduction

For data that needs to be stored across sessions, it is necessary to use a database for long-term storage. Learn more about the different data types here.

The following database integrations are currently working with Jovo v4:

  • FileDb: File-based system for local prototyping. Added to the app.dev stage by default.
  • DynamoDb: NoSQL database by AWS, typically used together with AWS Lambda.
  • MongoDb: Source-available NoSQL database.

The configuration section explains how database integrations can be added and configured.

If you want to build your own database integration, take a look at the custom database integration section

Configuration

You can add a database integration as a plugin. For example, many Jovo projects have FileDb added to app.dev.ts:

app.configure({
  plugins: [
    new FileDb({
      pathToFile: '../db/db.json',
    }),
    // ...
  ],
});

We recommend keeping FileDb for the dev stage and then adding a production database like DynamoDb to stages like prod. Learn more about staging here.

Along with integration specific options (which can be found in each integration's documentation), there are also features that are configured the same way across all databases. This section uses FileDb for its code examples, which can be replaced with the database integration of your choice.

By default, a database integration stores data like this:

{
  "id": "someUserId",
  "user": {
    "data": {}
  },
  "createdAt": "2021-06-30T05:50:04.034Z",
  "updatedAt": "2021-06-30T05:50:04.095Z"
}

It includes:

  • A user id to identify the current user. This is either taken from the platform (e.g. an Alexa Skill user ID) or created internally by Jovo.
  • A user object that stores user data.
  • Timestamps createdAt and updatedAt that help debug users in large datasets.

storedElements

There are also additional elements that can be stored in the database. These can be configured with storedElements, which makes it possible to granularly define which types of data should be stored in the database.

The default configuration for each database integration is this:

new FileDb({
  // ...
  storedElements: {
    user: true, // this.$user.data
    session: false, // this.$session.data
    history: false, // this.$history
    createdAt: true,
    updatedAt: true,
  }
}),
  • user: Persist user data across sessions using this.$user.data. Enabled by default.
  • session: Persist session data across interactions using this.$session.data. This is necessary for some platforms (like Facebook Messenger) that don't allow for session storage.
  • history: Persist an interaction history and define which elements (e.g. nlu or output) data you want to store from previous requests and responses.
  • createdAt and updatedAt: These timestamps are enabled by default.

Learn more about the different data types here.

session

Platforms like Facebook Messenger or Google Business Messages don't support session storage. This is why all session data needs to be persisted in a database.

new FileDb({
  // ...
  storedElements: {
    // ...
    session: true,
  }
}),

For platforms that do not have the concept of sessions, we need to define after which time a request should be seen as the start of the new session. The default is 15 minutes and can be modified with the expiresAfterSeconds option:

new FileDb({
  // ...
  storedElements: {
    // ...
    session: {
      expiresAfterSeconds: 900,
    }
  }
}),

If the option is added, the session field is automatically enabled. However, you can also add enabled if you like:

new FileDb({
  // ...
  storedElements: {
    // ...
    session: {
      enabled: true,
      expiresAfterSeconds: 900,
    }
  }
}),

Middlewares

Each database integration extends the DbPlugin class and hooks into the following RIDR middlewares:

  • Data is retrieved in request.start
  • Data is stored in response.end

If you want to build a plugin or hook that modifies the data, make sure that this happens between these two middlewares. See the RIDR middlewares section for an overview.

Custom Database Integration

You can create your own database integration as a DbPlugin, which is a special type of Jovo plugin.

For guidance, we recommend taking a look at the DynamoDB integration code, especially the DynamoDb.ts file.

The custom database needs to implement the following methods:

  • loadData: Load the data at the beginning of the request lifecycle. Needs to call the jovo.setPersistableData method.
  • saveData: Save the data at the end of the request lifecycle. Needs to call the jovo.applyPersistableData method.