# Mongoose

{% hint style="success" %}
This is the official documentation of the `@forestadmin/agent` Node.js agent.
{% endhint %}

The Mongoose data source allows importing collections from a Mongoose instance.

To make everything work as expected, you need to install the package `@forestadmin/datasource-mongoose`.

{% tabs %}
{% tab title="agent.js" %}

```javascript
const { createAgent } = require('@forestadmin/agent');
const { createMongooseDataSource } = require('@forestadmin/datasource-mongoose');
const connection = require('./mongoose-models');

// Create agent and import collections from mongoose.connection
const agent = createAgent(options).addDataSource(
  createMongooseDataSource(connection, { flattenMode: 'none' }),
);
```

{% endtab %}

{% tab title="mongoose-models.js" %}

```javascript
const mongoose = require('mongoose');

const connectionString = 'mongodb://root:password@localhost:27017';
const connection = mongoose.createConnection(connectionString);

connection.model(
  'persons',
  new mongoose.Schema({
    name: String,
    age: Number,

    // Nested object
    address: { streetName: String, city: String, country: String },

    // List of nested objects
    bills: [{ title: String, amount: Number, issueDate: Date, payedBy: [String] }],
  }),
);

module.exports = connection;
```

{% endtab %}
{% endtabs %}

### Dealing with deeply nested models

![One Mongoose collection split into four Forest-Admin collections](/files/l1WclPq1T7wn0tC8LCCB)

When passing `flattenMode: 'none'` to the Mongoose data source, the connector will map each Mongoose model to a single Forest Admin collection without transformations.

As models in Mongoose can be deeply nested, that may not be what you want:

* Nested references will not be displayed as relations.
* JSON editors will be displayed for nested data.

#### Understanding `flattenMode`

|                         | Description                                                                                                                                                 |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `flattenMode: 'auto'`   | Arrays of objects and arrays of references are converted to independent Forest Admin collections. All other fields are moved to the root of each collection |
| `flattenMode: 'manual'` | You are in full control on which virtual collections are created, and which fields are moved                                                                |
| `flattenMode: 'none'`   | No transformation are made: Forest Admin collection use the exact same structure than your Mongoose models                                                  |
| `flattenMode: 'legacy'` | Retro-compatibility with previous versions                                                                                                                  |
| not defined             | Equivalent to `legacy` but a warning is displayed at server startup                                                                                         |

{% hint style="warning" %}
The forest admin agent may need to create "virtual" collections to represent relationships, especially in `flattenMode: 'auto'`. If you use this mode along with the [include collection whitelist mode](/developer-guide-agents-nodejs/agent-customization/agent-customization.md#removing-collections), check that you also include useful relationship collections.
{% endhint %}

#### Example

Supposing that `persons` records have the following format:

```json
{
  "name": "Sherlock Holmes",
  "age": 54,
  "address": {
    "streetName": "Baker Street",
    "city": "London",
    "country": "Great Britain"
  },
  "bills": [
    {
      "title": "Rent",
      "amount": 0,
      "issueDate": "1887-04-17",
      "payedBy": ["Sherlock", "John", "Mrs Hudson"]
    }
  ]
}
```

The following samples are equivalent, and will import two collections into your Forest Admin panel:

* `persons` with the following fields: `name`, `age`, `address->streetName`, `address->city`, `address->country`.
* `persons_bills` with the following fields: `title`, `amount`, `issueDate`, `payedBy`.

```javascript
// Automatic mode
const dataSource = createMongooseDataSource(mongoose.connection, {
  flattenMode: 'auto',
});

// Manual mode
const dataSource = createMongooseDataSource(mongoose.connection, {
  flattenMode: 'manual',
  flattenOptions: {
    // name of the Mongoose model
    persons: {
      // paths that should be converted to independent collections
      asModels: ['bills'],

      // paths that should be moved to the root of the collection
      asFields: ['address'],
      // or
      // asFields: ['address.streetName', 'address.city', 'address.country'],
      // or
      // asFields: [{ field: 'address', level: 1 }],
    },
  },
});
```

### Data Navigation

When customizing your agent, you will need to navigate through your data efficiently.\
This section explains how to structure paths based on different field types.

#### Separator Behavior

There are two different separators depending on the field type:

* **Nested Fields (`@@@`)** – Used when accessing a nested field.
* **Related Data (`:`)** – Used when accessing related data.

#### Example

Consider a `User` collection with an `address` relation that contains a `city` field,\
which itself has a nested `name` field.

`User (collection) → address (relation) → city (field) → name (nested field)`

To access the `name` field inside `city`, the path would be:

**`address:city@@@name`**

This structure ensures a clear distinction between relationships and nested properties.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestadmin.com/developer-guide-agents-nodejs/data-sources/provided-data-sources/mongoose.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
