
Содержание статьи
В этой статье вы потренируете свои навыки 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» и т.д.
Как сохранить данные в базе данных

Ладно, теперь, когда у нас есть некоторые данные, давайте сохраним их в 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().
Как запросить данные

После того как 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")
}
}
Еще одна распространенная функция, которую мы хотим иметь, – это обновление существующих записей в базе данных.

После внедрения наших функций мы экспортируем функции для использования из нашего приложения 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)
})
Подведению!

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