<commit_before><img src="https://raw.githubusercontent.com/EddyVerbruggen/nativescript-plugin-firebase/master/docs/images/features/firestore.png" height="85px" alt="Cloud Firestore"/>

## Enabling Firestore
During plugin installation you'll be asked whether or not you use Firestore.

In case you're upgrading and you have the `firebase.nativescript.json` file in your project root, edit it and add: `"firestore": true`.
Then run `rm -rf platforms && rm -rf node_modules && npm i`.

## Functions
All of these are 100% compatible with the Firestore Web API to make it easy to share code between web and native, and you can
refer to the [Firestore web api docs](https://firebase.google.com/docs/firestore/data-model) (make sure to look at the 'WEB' tab of those code samples).

### `init` / `initializeApp`
By default Firestore on iOS and Android persists data locally for offline usage (web doesn't by default, and the regular Firebase DB doesn't either on any platform).
If you don't like that awesome feature, you can pass `persist: false` to the [`init` function](../README.md#init).

> Note that `initializeApp` is simply an alias for `init` to make the plugin compatible with the web API.

```typescript
const firebase = require("nativescript-plugin-firebase/app");

firebase.initializeApp({
  persist: false
});
```

### `collection`
A 'collection' is at the root of any Firestore interaction. Data is stored as a 'document' inside a collection.

```typescript
const citiesCollection = firebase.firestore().collection("cities");
```

### `collection.get()`
To get all documents inside a collection:

```typescript
const citiesCollection = firebase.firestore().collection("cities");

citiesCollection.get().then(querySnapshot => {
  querySnapshot.forEach(doc => {
    console.log(`${doc.id} => ${JSON.stringify(doc.data())}`);
  });
});
```

### `collection().onSnapshot()`
To listen to changes in a certain collection, you can register a callback function that gets invoked every time data is changed.

To unsubscribe the listener, just invoke the function that was returned when attaching the listener.

> NOTE: Due to a bug in the iOS Firestore SDK 'unsubscribe' does not currently work (plugin version 5.0.0), so the plugin is silently ignoring further updates after unsubscribing. This should not hurt your usage in any way though.

```typescript
const citiesCollection = firebase.firestore().collection("cities");

const unsubscribe = citiesCollection.onSnapshot((snapshot: firestore.QuerySnapshot) => {
  snapshot.forEach(city => console.log(city.data()));
});

// then after a while, to detach the listener:
unsubscribe();
```

> Using **Observables**? [Check the example in the demo app](https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/f6972433dea48bf1d342a6e4ef7f955dff341837/demo-ng/app/item/items.component.ts#L187-L198).

#### Snapshot metadata (for queries and documents)
Firestore can return metadata when passing the `includeMetadataChanges` boolean property. This can be used for:

- `snapshot.metadata.fromCache`: True if the snapshot was created from cached data rather than guaranteed up-to-date server data.
- `snapshot.metadata.hasPendingWrites`: True if the snapshot contains the result of local writes that have not yet been committed to the backend.

```typescript
import { firestore } from "nativescript-plugin-firebase";
const citiesCollection = firebase.firestore().collection("cities");

const unsubscribe = citiesCollection.onSnapshot(({ includeMetadataChanges: true }, snapshot: firestore.QuerySnapshot) => {
  snapshot.forEach(city => console.log(city.data()));

  console.log("Data came from " + (snapshot.metadata.fromCache ? "local cache" : "server"));
  console.log("Has pending writes? " + snapshot.metadata.hasPendingWrites);
});

// then after a while, to detach the listener:
unsubscribe();
```

### `collection.doc()`
As mentioned, a document lives inside a collection and contains the actual data:<commit_msg>[docs] - Update firestore docs for onSnapshot<commit_after><img src="https://raw.githubusercontent.com/EddyVerbruggen/nativescript-plugin-firebase/master/docs/images/features/firestore.png" height="85px" alt="Cloud Firestore"/>

## Enabling Firestore
During plugin installation you'll be asked whether or not you use Firestore.

In case you're upgrading and you have the `firebase.nativescript.json` file in your project root, edit it and add: `"firestore": true`.
Then run `rm -rf platforms && rm -rf node_modules && npm i`.

## Functions
All of these are 100% compatible with the Firestore Web API to make it easy to share code between web and native, and you can
refer to the [Firestore web api docs](https://firebase.google.com/docs/firestore/data-model) (make sure to look at the 'WEB' tab of those code samples).

### `init` / `initializeApp`
By default Firestore on iOS and Android persists data locally for offline usage (web doesn't by default, and the regular Firebase DB doesn't either on any platform).
If you don't like that awesome feature, you can pass `persist: false` to the [`init` function](../README.md#init).

> Note that `initializeApp` is simply an alias for `init` to make the plugin compatible with the web API.

```typescript
const firebase = require("nativescript-plugin-firebase/app");

firebase.initializeApp({
  persist: false
});
```

### `collection`
A 'collection' is at the root of any Firestore interaction. Data is stored as a 'document' inside a collection.

```typescript
const citiesCollection = firebase.firestore().collection("cities");
```

### `collection.get()`
To get all documents inside a collection:

```typescript
const citiesCollection = firebase.firestore().collection("cities");

citiesCollection.get().then(querySnapshot => {
  querySnapshot.forEach(doc => {
    console.log(`${doc.id} => ${JSON.stringify(doc.data())}`);
  });
});
```

### `collection().onSnapshot()`
To listen to changes in a certain collection, you can register a callback function that gets invoked every time data is changed.

To unsubscribe the listener, just invoke the function that was returned when attaching the listener.

> NOTE: Due to a bug in the iOS Firestore SDK 'unsubscribe' does not currently work (plugin version 5.0.0), so the plugin is silently ignoring further updates after unsubscribing. This should not hurt your usage in any way though.

```typescript
const citiesCollection = firebase.firestore().collection("cities");

const unsubscribe = citiesCollection.onSnapshot((snapshot: firestore.QuerySnapshot) => {
  snapshot.forEach(city => console.log(city.data()));
});

// then after a while, to detach the listener:
unsubscribe();

/**
 * If you pass in SnapshotOptions for the first parameter then your next should be onNext and
 * onError if you want for the third parameter. If you pass onNext as the first parameter the
 * second will be interpreted as onError callback. Note that you could pass onComplete, but
 * it will never be called as stated by Firestore docs.
 *
 * onError callbacks are optional!
 * onSnapshot(p1: SnapshotListenOptions|onNextCallback, p2?: onNextCallback | onErrorCallback, p3?: onErrorCallback?)
 */
const docRef: firestore.DocumentReference = firebase.firestore().collection("cities").doc("SF");
docRef.onSnapshot(
    {includeMetadataChanges: true},   // Comment out if you just want onNext && onError callbacks
    (doc: firestore.DocumentSnapshot) => {

      const source = doc.metadata.fromCache ? "local cache" : "server";
      console.log("Data came from " + source);
      console.log("Has pending writes? " + doc.metadata.hasPendingWrites);
    },
    (error: Error) => {
      console.error(error);
    }
  );
```

> Using **Observables**? [Check the example in the demo app](https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/f6972433dea48bf1d342a6e4ef7f955dff341837/demo-ng/app/item/items.component.ts#L187-L198).

#### Snapshot metadata (for queries and documents)
Firestore can return metadata when passing the `includeMetadataChanges` boolean property. This can be used for:

- `snapshot.metadata.fromCache`: True if the snapshot was created from cached data rather than guaranteed up-to-date server data.
- `snapshot.metadata.hasPendingWrites`: True if the snapshot contains the result of local writes that have not yet been committed to the backend.

```typescript
import { firestore } from "nativescript-plugin-firebase";
const citiesCollection = firebase.firestore().collection("cities");

const unsubscribe = citiesCollection.onSnapshot(({ includeMetadataChanges: true }, snapshot: firestore.QuerySnapshot) => {
  snapshot.forEach(city => console.log(city.data()));

  console.log("Data came from " + (snapshot.metadata.fromCache ? "local cache" : "server"));
  console.log("Has pending writes? " + snapshot.metadata.hasPendingWrites);
});

// then after a while, to detach the listener:
unsubscribe();
```

### `collection.doc()`
As mentioned, a document lives inside a collection and contains the actual data:
{'fraction_non_alphanumeric': 0.11282620766240978, 'fraction_numerical': 0.008995002776235425, 'mean_word_length': 5.068733153638814, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '302553', 'n_tokens_mistral': 2542, 'n_tokens_neox': 2450, 'n_words': 939}