# Data

## Schema

<figure><img src="https://3582814619-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3xQsR87sz0wbr4uZcoQW%2Fuploads%2Fov8OoG2neLSGflhzauCf%2Fimage.png?alt=media&#x26;token=650ee795-c229-4c44-8783-732195368bf8" alt=""><figcaption><p>Data Schema in FIrebase's Firestore Cloud Database</p></figcaption></figure>

Our schema consists of many different collections; Firestore is not a relational database and uses collections as opposed to tables. Unique identifiers are used to track users, animals, and other objects. Having said this, we are using Firestore relationally in practice.

**Pointers to Collections as Lists of a Certain Type**

<figure><img src="https://3582814619-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3xQsR87sz0wbr4uZcoQW%2Fuploads%2FFucc933ageNY3BVhOYl2%2Fimage.png?alt=media&#x26;token=fb17b10c-623f-4d33-b24f-7184b71643b3" alt=""><figcaption><p>Bounties Entry in Firestore</p></figcaption></figure>

<figure><img src="https://3582814619-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3xQsR87sz0wbr4uZcoQW%2Fuploads%2FDzuekyJ1JvM1MmCGLSAQ%2Fimage.png?alt=media&#x26;token=cb6a984b-8daf-47ac-b5d0-c84d44778a16" alt=""><figcaption><p>Bounty Collection with Single Item</p></figcaption></figure>

Because we are using initializer data, it may be difficult to see why this is important to include. We created our schema in such a way that it could be easily integrated with Typescript model files:

<figure><img src="https://3582814619-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3xQsR87sz0wbr4uZcoQW%2Fuploads%2FvCbG1d2kvBRSMQBUAuSE%2FScreenshot%20(301).png?alt=media&#x26;token=94db090d-2f7b-49a7-8502-37eaa065c69d" alt=""><figcaption><p>Bounties Interface</p></figcaption></figure>

<figure><img src="https://3582814619-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3xQsR87sz0wbr4uZcoQW%2Fuploads%2FOMyI9yNXrHGsjCWHFzt7%2FScreenshot%20(302).png?alt=media&#x26;token=85eb649e-46fd-42c6-a69f-65447db07443" alt=""><figcaption><p>Bounty Interface</p></figcaption></figure>

The **bountiesList** variable is a list of objects of type **Bounty**. In Firestore, we use a list of **pointers** to the **Bounty** collection's relevant items.

**Relating Items by ID**

<figure><img src="https://3582814619-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3xQsR87sz0wbr4uZcoQW%2Fuploads%2FeORKlHZEgufTo9h6vRuk%2Fimage.png?alt=media&#x26;token=196fcd6e-e432-453f-9b0f-ce751684c22c" alt=""><figcaption><p>User Collection</p></figcaption></figure>

Suppose that any one user has several other files associated with him or her. If this is the case, these other objects have properties containing their owner userId for querying. Take, for example, this user's userId 1234567. If you wanted to find other objects owned by this user (or vice versa -- find the user from an object), you can query the targeted collection of items and filter by userId.

**Using Interfaces Dynamically**

```typescript
this.userService.getUser('userId').subscribe((user: User) => {
 this.user = user;
});
```

Here, we're creating a subscription to the **getUser** service function and casting the returned object (user) to the **User** interface type automatically. It's important to remember that observables represent a stream of data associated with other objects, so this is not exclusive to a return of just one object. Every object passed through the observable could be cast to this type. It depends on the return value of the observable.

***

## Firestore

Data imported or exported to Firestore using an interface conversion as well.

```typescript
import { firestore } from "firebase-admin";

const converter = <T>() => ({
 toFirestore: (data: T) => data,
 fromFirestore: (snap: FirebaseFirestore.QueryDocumentSnapshot) => snap.data() as T
});

...

const animals = firestore().collection('Animal').withConverter(converter<Animal>());

...
animals.get().then((querySnapshot) => {
 const animalsData: Animal[] = [];
 querySnapshot.forEach((doc) => {
    animalsData.push(doc.data());
 });
});
```

This is an implementation for mapping Firestore data to a specific interface. It starts by defining a **converter** function that specifies how to convert data to/from Firestore. This converter is then applied to a Firestore collection reference using Firestore's **withConverter** method. Finally, all documents from the collection are mapped to their specified data type.

***
