# How to work with Embedded  documents and References in MongoDB

## Overview

MongoDB is a NoSQL database and does not support classic relationships as in SQL databases. However, you can build references across entities in MongoDB in a couple of ways -

* Inner objects (equivalent to embedded documents, i.e., documents nested within another document)
* References across collections using an ObjectID field in a collection to reference an ID in another collection

For a more comprehensive overview on this topic, refer to MongoDB's docs on [Embedded Data Versus References](https://www.mongodb.com/docs/manual/data-modeling/concepts/embedding-vs-references/). In this guide, we will see how you can work with inner objects and references in MongoDB with Neurelo.

## Inner Objects (Embedded Documents)

An embedded document in MongoDB is a document nested inside another MongoDB document. That is, it is not just a reference to another document but it is fully contained within the parent document.

In the Neurelo Schema Language and in the APIs, embedded documents can be used as **innerObjects**.

For example, consider the following document

```json
{
  "_id": "5fc89ecd1e602ff6c856e811",
  "name": "Twinkle Truffles",
  "flavor": "Milk Chocolate",
  "brand": "Cadbunny's",
  "price": 2.99,
  "inStock": true,
  "nutritionalInfo": {
    "calories": 250,
    "fat": "10g",
    "sugar": "25g",
    "protein": "5g"
  }
}
```

Here, `nutritionalInfo` is an inner object.

Inner objects enhance read performance by reducing database queries and ensuring atomic updates within a single document. They are optimal for closely related data that is frequently accessed together, remains relatively static, and adheres to the 16MB MongoDB document size limit. However, they might lead to data redundancy and scalability challenges as your database grows.

The Neurelo Schema for this will be something like this -

```json
{
  "objects": {
    "foodItem": {
      "properties": {
        "id": {
          "type": "string",
          "identifier": true,
          "sourceName": "_id",
          "sourceType": "ObjectId",
          "default": {
            "function": "auto"
          }
        },
        "name": {
          "type": "string"
        },
        "flavor": {
          "type": "string"
        },
        "brand": {
          "type": "string"
        },
        "price": {
          "type": "number",
          "format": "float"
        },
        "inStock": {
          "type": "boolean"
        },
        "nutritionalInfo": {
          "$ref": "#/innerObjects/nutritionalInfo"
        }
      }
    }
  },
  "innerObjects": {
    "nutritionalInfo": {
      "properties": {
        "calories": {
          "type": "integer"
        },
        "fat": {
          "type": "string"
        },
        "sugar": {
          "type": "string"
        },
        "protein": {
          "type": "string"
        }
      }
    }
  }
}
```

For guidance on building APIs using inner objects, refer to the API reference materials for [REST](/neurelo-api-reference-rest.md) and [GraphQL](/neurelo-api-reference-graphql.md).

## References

References in MongoDB are used to link documents across different collections. This is a commonly used technique to represent one-to-one, one-to-many, or many-to-many relationships.

To do this, instead of embedding all data within a single document, we can reference data from other collections. For example, consider the following three documents from three different collections:

<figure><img src="/files/yOGRCZDK1TYGHOfLMhad" alt="" width="563"><figcaption></figcaption></figure>

Here, there is a one to one reference between `NutritionalInfo` and `Products`. Furthermore, there is a one to many reference between `Products` and `Reviews`.

The Neurelo Schema for this will be something like this -

<pre class="language-json"><code class="lang-json">{
<strong>  "objects": {
</strong>     "nutritionalInfo": {
      "properties": {
        "id": {
          "type": "string",
          "identifier": true,
          "sourceName": "_id",
          "sourceType": "ObjectId",
          "default": {
            "function": "auto"
          }
        },
        "calories": {
          "type": "string"
        },
        "fat": {
          "type": "string"
        },
        "sugar": {
          "type": "string"
        },
        "protein": {
          "type": "string"
        }
      }
    },
    "products": {
      "properties": {
        "id": {
          "type": "string",
          "identifier": true,
          "sourceName": "_id",
          "sourceType": "ObjectId",
          "default": {
            "function": "auto"
          }
        },
        "name": {
          "type": "string"
        },
        "flavor": {
          "type": "string"
        },
        "brand": {
          "type": "string"
        },
        "price": {
          "type": "number",
          "format": "float"
        },
        "inStock": {
          "type": "boolean"
        },
        "nutritionalInfoId": {
          "type": "string",
          "sourceType": "ObjectId"
        },
        "reviewIds": {
          "type": "array",
          "items": {
            "type": "string",
            "sourceType": "ObjectId"
          }
        }
      }
    },
    "reviews": {
      "properties": {
        "id": {
          "type": "string",
          "identifier": true,
          "sourceName": "_id",
          "sourceType": "ObjectId",
          "default": {
            "function": "auto"
          }
        },
        "productId": {
          "type": "string",
          "sourceType": "ObjectId"
        },
        "rating": {
          "type": "integer"
        },
        "comment": {
          "type": "string"
        }
      }
    }
  }
}
</code></pre>

Unlike embedded documents, references are more suitable for large or frequently changing data. They excel in many-to-many relationships by offering flexibility to link documents across different collections, preventing data duplication, and maintaining database normalization. However, this approach may require additional queries to access related data, potentially affecting performance.

Now, consider the same database structure as shown in the example above. To create references using Neurelo, it is important to structure your create queries in a specific order. This will ensure that all documents are created in the correct sequence to initiate the references between them. For instance,

* You can begin by creating the `NutritionalInfo` document, as this does not depend on any other documents.
* Next, you can create the `Products` document. Initially, you can include the `nutritionalInfoId` with the ID of the previously created `NutritionalInfo` document and initialize the `reviewIds` with an empty array.
* After this, you can proceed with creating individual `Reviews` documents, where each document references the `productId` of the `Products` document.
* And finally, you can update the `Products` document to include the `_id`s of the newly created `Reviews` documents.

For guidance on building create and update APIs, refer to the API reference materials for [REST](/neurelo-api-reference-rest.md) and [GraphQL](/neurelo-api-reference-graphql.md).


---

# 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.neurelo.com/guides/how-to-work-with-embedded-documents-and-references-in-mongodb.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.
