> For the complete documentation index, see [llms.txt](https://docs.tivity.one/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tivity.one/extensibility-and-integration/adapter-portfolio/mongodb-adapter.md).

# MongoDB Adapter

## Getting Started

* Host, port, authentication database and database must be configured (authentication database and database can be equal)
* Username and password must be provided (anonymous usage is not supported)
* Class mapping keys for root documents must always start with the collection name:&#x20;
* Class mapping keys for nested arrays must include the nested path prefixed by a $: **$**
* Class mapping keys for multiple nested arrays must be separated by a #: **$#**
* Nested paths cannot be skips, thus for a double nested array three classes must exist (root, nested and nested in nested)
* Field mapping keys must always be relative:  (for root documents and nested arrays)
* Field mapping keys for nested documents must be separated by a dot **.**
* Field mapping keys for parent fields must be absolute prefixed with by a $: **$**
* Field mapping data types must match (see data types for more)
* ID fields as identity must be present for all classes (must be unique; can be any data type)
* Parent fields must be present for nested arrays and should be identical to the parent class ID field
* Parent fields should be read-only (there will not be updated or inserted anyway)

### Data types

(see <https://docs.mongodb.com/manual/reference/bson-types/> for more)

| Platform/Source | other | double  | string | objectId | bool  | date  | int     | long    | decimal |
| --------------- | ----- | ------- | ------ | -------- | ----- | ----- | ------- | ------- | ------- |
| Other           | Error | Error   | Error  | Error    | Error | Error | Error   | Error   | Error   |
| Guid            | Error | Error   | Parse  | Error    | Error | Error | Error   | Error   | Error   |
| Boolean         | Error | Error   | Parse  | Error    | Value | Error | Error   | Error   | Error   |
| String          | Error | Parse   | Value  | Parse    | Parse | Parse | Parse   | Parse   | Parse   |
| DateTime        | Error | Error   | Parse  | Error    | Error | Value | Error   | Error   | Error   |
| Integer         | Error | Value\* | Parse  | Error    | Error | Error | Value   | Value\* | Value\* |
| Byte            | Error | Value\* | Parse  | Error    | Error | Error | Value\* | Value\* | Value\* |
| Short           | Error | Value\* | Parse  | Error    | Error | Error | Value\* | Value\* | Value\* |
| Long            | Error | Value\* | Parse  | Error    | Error | Error | Value\* | Value   | Value\* |
| Float           | Error | Value\* | Parse  | Error    | Error | Error | Value\* | Value\* | Value\* |
| Double          | Error | Value   | Parse  | Error    | Error | Error | Value\* | Value\* | Value\* |
| Numeric         | Error | Value\* | Parse  | Error    | Error | Error | Value\* | Value\* | Value   |
| Char            | Error | Value\* | Parse  | Error    | Error | Error | Value   | Value\* | Value\* |

* Value  = value used
* Value\* = value used, fails on data loss
* Parse  = string parsed, fails on format error
* Error  = fails always

### Examples:

Class "Project" mapped to "projects" with the following fields:

| Platform key | Platform type | Source key   | Source type | Other    |
| ------------ | ------------- | ------------ | ----------- | -------- |
| ID           | String        | \_id         | objectId    | identity |
| Title        | String        | title        | string      |          |
| Start        | DateTime      | period.start | date        |          |
| End          | DateTime      | period.end   | date        |          |

Class "Task" mapped to "projects$tasks" with the following fields:

| Platform key  | Platform type | Source key    | Source type | Other     |
| ------------- | ------------- | ------------- | ----------- | --------- |
| ID            | String        | \_id          | objectId    | identity  |
| ParentID      | String        | $\_id         | objectId    | read-only |
| Title         | String        | title         | string      |           |
| Description   | String        | description   | string      |           |
| RemainingWork | Integer       | remainingWork | int         |           |

Class "Comment" mapped to "projects$tasks#comments" with the following fields:

| Platform key | Platform type | Source key  | Source type | Other     |
| ------------ | ------------- | ----------- | ----------- | --------- |
| ID           | String        | \_id        | objectId    | identity  |
| ParentID     | String        | $tasks.\_id | objectId    | read-only |
| Content      | String        | content     | string      |           |

Sample document in collection "projects":

```javascript
{
  "_id": { "$oid": "5fcd1c3c1f028fce28332d9d" },
  "title": "Project1",
  "period": {
    "start": { "$date": "2020-12-16T00:00:00.000+00:00" },
    "end": { "$date": "2020-12-17T00:00:00.000+00:00" }
  },
  "tasks": [
    {
      "_id": { "$oid": "5fcd1c3c1f028fce28332d9d" },
      "title": "Task1",
      "description": "Description of Task1",
      "remainingWork": 8,
      "comments": [
        {
          "_id": { "$oid": "5fcd2b466b0df14c8839d04d" },
          "content": "Content1"
        }
      ]
    }
  ]
}
```

## Capabilities

### Authentication

* User will be authenticated to the authentication database configured
* The connection string is entered directly. The connection string must not contain the credentials and the step must mention that the credentials will be added by the adapter.

### Data

* Documents will not be inserted through create, but through update new
* All read methods are not implemented, since they are not used when the query capability is present
* Insert, update and delete differs heavily between root documents and nested arrays
* To effectively manage CRUD operations a special mapping is provided
* Data times will be converted to local culture (MongoDB saves them always as UTC)

### Query

* The logical operator `And` takes priority over `Or` in execution order
* Condition values are given as strings and thus converted using the local culture
