Учебник по Node.js и Cloud Firestore – Как создать систему домашнего инвентаря

uchebnik po nodejs i cloud firestore – kak sozdat sistemu

В этой статье вы потренируете свои навыки JavaScript, а также упростите домашние дела, создав собственную систему домашнего инвентаря.

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

Уставший отслеживать вручную, я решил создать собственную систему домашнего инвентаря. Эта система позволит мне:

  • создавать записи для каждого товара вместе с полезной информацией, например цена и количество
  • фильтровать товары на основе различных критериев, таких как цена, количество и срок годности
  • сортировать элементы по заданным критериям
  • удалить неиспользуемые элементы
  • редактировать имеющиеся записи

В этом учебнике я расскажу вам, как я построил эту систему. Давайте начнем.

Как определить схему базы данных

Cloud Firestore – это облачная, масштабируемая, гибкая база данных NoSQL, которую предлагает Firebase. Данные хранятся в документах, а документы группируются в коллекции, подобно хранению страниц информации в файле и хранению нескольких файлов вместе в ящике.

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

Для наших целей определим коллекцию для определенной категории. Каждый документ будет соответствовать продукту в этой категории, а содержимое документа будет каждое поле информации вместе с его значением данных. Например:

"Snacks" : {
	"Food_Item_1" : { "Price":P1, "Quantity":Q1, "ExpiryDate":D1},
	"Food_Item_2" : { "Price":P2, "Quantity":Q2, "ExpiryDate":D2},	
    .
    .
	"Food_Item_N" : { "Price":PN, "Quantity":QN, "ExpiryDate":DN}
}

Название нашей коллекции – Закуски, названия наших документов – Food_Item_1, Food_Item_2 и так далее, а содержимое каждого документа – цена, количество и срок годности.

Как получить информацию от пользователя

Давайте сначала создадим несколько маршрутов и представлений и импортируем необходимые модули узлов.

const express = require("express")
const app = express()
//Middleware to parse data in body portion of incoming request, like POST //request
const body_parser = require("body-parser")

objForUrlencoded = body_parser.urlencoded({extended:false})

app.set("view engine", "ejs")
app.use("/assets", express.static("assets"))
app.use(objForUrlencoded)

app.get("/", (req,res,next)=>{//Show the homepage
	res.render("homepage")
})
app.get("/save_data.ejs", (req,res,next)=>{//Show the form for saving data
	res.render("save_data")
})
app.get("/search_data.ejs", (req,res,next)=>{//Show the form for searching data
	res.render("search_data")
})

app.listen(1337, ()=>{ console.log("Listening on port 1337")})

Здесь мы определяем простую программу Express, которая прослушивает порт 1337 и воспроизводит страницы, как указано методом HTTP (GET, POST) и URL-адресом. Мы создаем простую форму для ввода пользователя.

Имейте в виду, что каждое поле ввода HTML должно иметь атрибут name, который впоследствии будет служить ключом для доступа к соответствующим значениям поля ввода. Например:

<input type="text" name="productName">
<br/><br/>
<label for="productCategory">Product Category:</label>
<select name="productCategory">
	<option value="Snacks">Snacks</option>
	<option value="Biscuits">Biscuits</option>
     <option value="Spices">Spices</option>
</select>
<br/><br/>
<label for="price">Price:</label>
  <input type="number" name="price">
<br/><br/>
<label for="quantity">Quantity:</label>
  <input type="number" name="quantity">

Позже мы сможем получить доступ к названию продукта как значению ключа «productName», к категории продукта как значению ключа «productCategory» и т.д.

Как сохранить данные в базе данных

изображение-124
Простой UI системы домашнего инвентаря

Ладно, теперь, когда у нас есть некоторые данные, давайте сохраним их в Firestore! Это включает в себя настройку учетной записи службы, получение секретного ключа и использование его для инициализации объекта Credentials для подключения базы данных к нашей программе с помощью Firebase Admin API.

Для получения более подробного объяснения процесса вы можете просмотреть их документацию.

/*Set up Admin API for Firebase*/
const admin = require('firebase-admin');
//Define path to secret key generated for service account
const serviceAccount = require(PATH TO KEY);
//Initialize the app
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

Здесь мы использовали путь к секретному ключу, являющемуся файлом JSON. Вы можете сделать то же самое, определив переменные среды, как описано здесь.

Далее мы храним наши данные в Firestore, используя метод set следующим образом:

let db = admin.firestore()

//Depending on your schema, save data by specifying the collection name, //document name and data contents as follows
await db.collection(key).doc(prod).set(save_to_database[key][prod])

Вот несколько терминов, с которыми вы должны быть знакомы во время навигации в документации Firestore, включая ссылку на API:

  • CollectionReference – этот объект используется для добавления документов, получения DocumentReferences и запроса документов.
  • Ссылка на документ – это расположение документа в базе данных, которое используется для чтения/записи/прослушивания этого места.
  • Снимок запроса – объект, содержащий результаты запроса
  • Снимок документа – содержит данные, считываемые из документа. Данные можно извлечь с помощью метода .data().

Как запросить данные

изображение-125
Простой пользовательский интерфейс для поиска/фильтрации данных

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

Скажем, мы хотим узнать сколько товаров у нас есть с категорией «Закуски». Каждый раз, когда мы выполняем запрос, мы получаем QuerySnapshot, являющийся списком DocumentSnapshots.

//Get all docs under the given category
helper_func_get_data = async (category, db) => {
	const data = await db.collection(category).get()
	if(data.empty)
		{
			return -1
		}
	else return data

}

Мы можем проверить, вернул ли запрос вообще какие-либо данные, используя свойство .empty, и перебрать все полученные документы с помощью функции forEach так:

data.forEach((doc) => { Product_Info[doc.id] = doc.data()})

//Here data is a QuerySnapshot and Product_Info is a JavaScript object 
//with document names as keys and their corresponding values. We can pass this 
//object as an argument in render() method to display the received contents

Вот как определить общую стоимость всех закусок:

total_agg = 0
data.forEach((doc) => { total_agg+=doc.data()[aggregate_over]

//aggregate_over is a variable which defines criteria to sum over like price //or quantity

Чтобы отсортировать все закуски по цене, выполните следующие действия.

const data = await db.collection(category).orderBy(filter_criteria).get() 

где filter_criteria=»Цена».

Как удалить элементы из базы данных

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

Пока не найдется возможный механизм для подключения холодильника к Cloud Firestore, нам придется вручную удалить записи о закусках, когда мы их съели.

firebase_delete_data = async (category, response, product_name) => {
	try
	{ 
	  let db = admin.firestore()
	  await db.collection(category).doc(product_name).delete()
	  response.render("search_data")
	   }
	catch(err)
	{console.log(err)}
}

Как обновить элементы в базе данных

firebase_update_data = async (category, response, reqbody) => {
	try
	{
		let db = admin.firestore()
		await db.collection(category).doc(reqbody["productName"]).update({"Price": parseFloat(reqbody["price"]), "Quantity": parseFloat(reqbody["quantity"]), "ExpiryDate": reqbody["expiryDate"]})
		response.render("successpage")
	}
	catch(err)
	{
		console.log(err)
		response.render("failurepage")
	}
}

Еще одна распространенная функция, которую мы хотим иметь, – это обновление существующих записей в базе данных.

изображение-126
Простой пользовательский интерфейс для обновления информации о продукте

После внедрения наших функций мы экспортируем функции для использования из нашего приложения Express следующим образом:

module.exports = {
	"firebase_save_data" : firebase_save_data,
	"firebase_retrieve_data": firebase_retrieve_data,
	"firebase_delete_data": firebase_delete_data,
	"firebase_update_data": firebase_update_data
	}

и импортируйте необходимый модуль следующим образом:

const firebase_functions = require("./firebase_CRUD_custom_code/firebase_functions.js")

Тогда мы можем использовать наши функции по необходимости. К примеру, если мы хотим обновить какие-то элементы, мы можем сделать следующее:

app.post("/update", objForUrlencoded, (req,res) => {
	
	firebase_functions.firebase_update_data(req.body["category"], res, req.body)
})

Подведению!

изображение-127

Подводя итог, в этой статье мы узнали о модели данных Cloud Firestore, как хранить данные, механизме получения данных, как работать с QuerySnapshots, сортировать данные по разным фильтрам, удалять элементы и обновлять элементы через нашу программу Express. .

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

Надеюсь, вам понравилось читать эту статью так же, как и мне. Спасибо за ваше время, хороший день и счастливую кодировку!

Добавить комментарий

Ваш адрес email не будет опубликован.