Привет, ребята! Это время пожарной базы. В прошлый раз мы говорили об Аутентификации в Firebase. Теперь пришло время базы данных.

Я Ахмед Абдельбасет, разработчик интерфейса React.js, мне 20 лет, я из Египта. Я разработчик-самоучка, я начал изучать веб-разработку в 2019 году и буду учиться вечно.

В этом блоге мы говорим о Firestore, установке, методах CRUD, правилах безопасности и обработке ошибок.

Что такое Firestore?

Firestore — это база данных NoSQL, которая хранит данные в документах и ​​коллекциях. Это база данных в режиме реального времени, которая позволяет хранить и синхронизировать данные между пользователями в режиме реального времени.

В чем разница между FirebaseFirestore и базой данных Firebase Realtime?

Настройка Firestore:

Начать:

Перейдите в Консоль Firebase, затем выберите свой проект или создайте новый проект, затем перейдите к Firestore на левой боковой панели, затем выберите Create database на верхней панели навигации, затем выберите Start in test mode и нажмите Enable.

Установите Firebase:

npm install firebase

инициализировать приложение:

import { initializeApp } from "firebase/app";
const app = initializeApp({ ...firebaseAppConfig }); 
// firebaseConfig is an object we have got from firebase console

инициализировать магазин огня:

import { getFirestore } from "firebase/firestore";
const db = getFirestore(app);
// Assign the return to a variable we will need it.

Хорошо, теперь мы настроили firestore. Итак, давайте поговорим о ссылке в firestore.

Использованная литература:

Мы будем использовать CRUD для базы. поэтому нам нужно указать, над чем мы хотим работать. Например, если мы хотим получить данные о коллекции документов или получить данные об одном документе, создать документ, обновить или удалить его, нам нужно указать, над чем именно мы хотим работать с firebase.

Итак, у нас есть пара ссылок: коллекции и документы.

Для ссылки на коллекцию мы используем collection(databaseReference, collectionName), а `databaseReference` возвращает функция getFirestore(app). а второй аргумент — это имя коллекции.

import { collection } from "firebase/firestore";
// ...
const usersRef = collection(db, "users");

Для ссылки на один документ мы используем функцию doc(db, collectionName, docId, ...moreSpecifies[]?)

import { doc } from "firebase/firestore";
// ...
const userRef = doc(db, "users", "AhmedAbdelbaset");

Для обращения к запросу используйте функцию query(). мы рассмотрим вопросы далее

import { query, where } from "firebase/firestore";
// ...
const q = query(usersRef, where("age", ">", 18));

Перейдите в раздел запросов, чтобы увидеть все методы запросов.

КРУД:

Node: Каждая функция, которую мы скажем, является обещанием и возвращает snapshotObject, поэтому для ее использования вы можете использовать оба:

  • someFunction(...).then((snapshot)=>...).catch((error)=>...)
  • try {const snapshot = await someFunct(...)} catch (error) {...}

Запись данных: включает create, update, delete

Создавать:

Добавьте новый документ с автоматически сгенерированным идентификатором:

addDoc(collectionRef, data)

import { addDoc, collection } from "firebase/firestore";
// ...
const docRef = await addDoc(collection(db, "users"), {
	first: "Ada",
	last: "Lovelace",
	born: 1815,
});
// Here will create a document with auto-generated id like fsajf-laskf-aslkf-aslk

Добавьте новый документ с настраиваемым идентификатором:

setDoc(documentRef, data)

import { doc, setDoc } from "firebase/firestore";
// ...
const docRef = await setDoc(doc(db, "users", auth.currentUser.uid), {
	first: "Ada",
	last: "Lovelace",
	born: 1815,
});
// Here will create a document with id (auth.currentUser.uid value)

Метод setDoc() также можно использовать для обновления документа. Если документ не существует, он будет создан. И если он существует, обновите его.

Обновлять:

updateDuc(docRef, newData)

import { updateDoc, doc } from "firebase/firestore";
// ...
const docRef = await updateDoc(doc(db, "users", auth.currentUser.uid), {
	first: "Ada",
	last: "Lovelace",
	born: 1815,
});

Вы также можете обновить документ, используя метод setDoc(), он перезапишет весь документ.

Удалить:

deleteDoc(docRef)

import { deleteDoc, doc } from "firebase/firestore";
// ...
await deleteDoc(doc(db, "users", auth.currentUser.uid));

Здесь мы говорили о записи данных (создание, обновление, удаление), давайте поговорим о чтении.

Чтение данных: включает get, list

Получите единый документ:

getDoc(docRef)

import { getDoc, doc } from "firebase/firestore";
// ...
const docSnap = await getDoc(doc(db, "users", auth.currentUser.uid));
if (docSnap.exists()) {
	console.log("Document data:", docSnap.data());
} else {
	// doc.data() will be undefined in this case
	console.log("No such document!");
}

Он возвращает объект, это самые важные свойства и методы.

{
  exists: Boolean, // true if the docRef exists in the database
  data: () => ({readable data}), // return a javascript object
}

Получить несколько документов:

getDocs(collectionRef || query)

import { getDocs, collection } from "firebase/firestore";
// ...
const querySnapshot = await getDocs(collection(db, "users"));
querySnapshot.forEach((doc) => {
	// doc.data() is never undefined for query doc snapshots
	console.log(doc.id, " => ", doc.data());
});

Он возвращает объект, это самые важные свойства и методы.

{
  empty: Boolean, // if false there are data
  docs: DocSnapshoot[
    {
      id: string,
      data: () => return a readable data
    }
  ], 
  size: number,
}

Получайте обновления в реальном времени

мы используем onSnapshot(docRef || colRef, callbackWhenDataChange)

Прослушайте один документ:

import { onSnapshot, doc } from "firebase/firestore";
// ...
const unsubscribe = onSnapshot(
	doc(db, "users", auth.currentUser.uid),
	(doc) => {
		console.log("Current data: ", doc.data());
	}
);

Прослушать несколько документов:

import { onSnapshot, collection } from "firebase/firestore";
// ...
const unsubscribe = onSnapshot(collection(db, "users"), (querySnapshot) => {
	querySnapshot.forEach((doc) => {
		console.log(`${doc.id} => ${doc.data()}`);
	});
});

Чтобы прекратить прослушивание документа, вызовите функцию unsubscribe(), возвращаемую методом onSnapshot().

Переходим к самому смешному разделу

Методы запроса

Мы используем запросы, чтобы указать данные, которые мы хотим прочитать. Например Вы хотите получить данные не все. но последние 10 документов или данных с полем спецификации. если у нас есть данные по городам мира. мы можем отфильтровать данные и получить документы, которые (страна === «США»).

мы используем запрос в качестве аргумента для getDocs(query)

Вот все запросы:

  • where(key, operator, value) : фильтровать данные. where("country", "==", "USA") .
  • orderBy(key, direction) : orderBy("population", "desc")
  • limit(number) : limit(10)
  • startAt(value)
  • startAfter(docRef)
  • endAt(value)
  • endBefore(docRef)

where() операторы:

  • "==" равно
  • "!=" не равно
  • "<" меньше чем
  • ">" больше, чем
  • ">=" равно или больше, чем
  • "<=" равно или меньше
  • "in" для массивов
  • "not-in" для массивов
  • "array-contains" для массивов
  • "array-contains-any" для массивов

Пример:

import {
	getDocs,
	query,
	where,
	collection,
	limit,
	orderBy,
} from "firebase/firestore";
// ...
const q = query(
	collection(db, "users"),
	where("age", ">", 18),
	orderBy("age"),
	limit(10)
);
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
	// doc.data() is never undefined for query doc snapshots
	console.log(doc.id, " => ", doc.data());
});

Транзакции

Транзакции полезны, когда вы хотите обновить документ на основе его текущих данных. Например, вам может понадобиться обновить поле счетчика в документе или выполнить сложный расчет на основе текущих данных в документе.

import { runTransaction, getDoc, doc } from "firebase/firestore";
// ...
const docRef = doc(db, "users", auth.currentUser.uid);
runTransaction(async (transaction) => {
	const docSnap = await transaction.get(docRef);
	if (!docSnap.exists()) {
		throw "Document does not exist!";
	}
	const newPopulation = docSnap.data().population + 1;
	transaction.update(docRef, { population: newPopulation });
});

Пакетная запись

Вы можете использовать пакет для выполнения нескольких операций записи как одной атомарной единицы. Пакеты полезны, когда вы хотите обновить несколько документов одновременно.

import { writeBatch, doc, setDoc } from "firebase/firestore";
// ...
const batch = writeBatch(db);
batch.set(doc(db, "users", auth.currentUser.uid), { age: 18 });
batch.set(doc(db, "users", auth.currentUser.uid), { age: 19 });
batch.set(doc(db, "users", auth.currentUser.uid), { age: 20 });
await batch.commit();

Правила безопасности

Правила безопасности написаны на декларативном языке, который поддерживает общие выражения и функции. Вы можете использовать правила безопасности, чтобы контролировать, кто может читать и записывать данные в вашу базу данных.

Чтобы написать правила безопасности, перейдите на вкладку Rules в разделе Firestore консоли Firebase.

Я собираюсь написать специальный блог для ПРАВИЛ БЕЗОПАСНОСТИ. Чтобы получить его, убедитесь, что вы следуете за мной.

Цены

Firestore предоставляется бесплатно для первого 1 ГБ хранилища и 50 000 операций чтения и записи в день. После этого с вас будет взиматься плата за объем используемого вами хранилища и количество операций чтения и записи, которые вы выполняете.

Смотрите страницу с ценами для более подробной информации.

Обработка ошибок Firestore

Вот код ошибок и небольшое их описание. Я надеюсь, это поможет вам.

  • candelled: Операция была отменена (обычно вызывающим абонентом).
  • unknown: Неизвестная ошибка или ошибка из другого домена ошибок.
  • `invalid-argument`: Клиент указал недопустимый аргумент.
  • `deadline-exceeded`: Крайний срок истек до завершения операции.
  • `not-found`: Какой-то запрошенный документ не найден.
  • `already-exists`: Какой-то документ, который мы пытались создать, уже существует.
  • `permission-denied`: у вызывающего объекта нет разрешения на выполнение указанной операции.
  • `resource-exhausted`: Некоторые ресурсы были исчерпаны, возможно, квота на пользователя или, возможно, во всей файловой системе закончилось место.
  • `failed-precondition`: Операция отклонена, так как система не находится в состоянии, необходимом для выполнения операции.
  • `aborted`: Операция была прервана, как правило, из-за проблемы параллелизма, такой как прерывание транзакции и т. д.
  • `out-of-range`: Попытка операции вышла за допустимый диапазон.
  • `unimplemented`: Операция не реализована или не поддерживается/не включена в этой службе.
  • `internal`: Внутренние ошибки.
  • `unavailable`: В данный момент услуга недоступна. Скорее всего, это временное состояние, и его можно исправить, повторив попытку с отсрочкой.
  • `data-loss`: Невосстановимая потеря или повреждение данных.
  • `unauthenticated`: запрос не содержит действительных учетных данных для операции.

Продолжай учиться

Документация о пожарном магазине

Здесь мы получили это!

Не пропустите мой предыдущий блог Аутентификация в Firebase. и если вы хотите получить Хранилище, Реальное время, Хостинг, ИИ и многое другое. Убедитесь, что вы следуете за мной.

Если этот блог приносит вам пользу, пожалуйста, оставьте приятный комментарий и похлопайте, если хотите.

Хороший взлом!