firebase创建数据库_在使用Firebase Cloud Firestore的React中设置数据库

firebase创建数据库

Storing and retrieving data can be a pain when working in an environment that focuses more on the “V” part of an MVC framework such as React. For most applications, I use Firebase Cloud Firestore to store and manage data because it handles the “Model” part pretty well.

在更加关注MVC框架的“ V”部分(例如React)的环境中工作时,存储和检索数据可能会很麻烦。 对于大多数应用程序,我使用Firebase Cloud Firestore来存储和管理数据,因为它可以很好地处理“模型”部分。

In this article, I will demonstrate how I use Cloud Firestore to save and query data in a React environment. The example project I’ll be using is called Burger Builder, an application that lets you order burgers from a menu and see your previous orders. An administrator would be able to create new varieties to be added to the menu. The code for this example project is in the Burger Builder Github repo.

在本文中,我将演示如何使用Cloud Firestore在React环境中保存和查询数据。 我将使用的示例项目称为Burger Builder,该应用程序可让您从菜单中订购汉堡并查看以前的订单。 管理员将能够创建要添加到菜单的新品种。 此示例项目的代码在Burger Builder Github存储库中

什么是Firestore? (What is Firestore?)

Firestore is a Firebase NoSQL database product with strong user-based security that makes storing, syncing, and querying data very easy. The user interface is also very intuitive, so it’s easy to wrap your head around how to best structure your data.

Firestore是Firebase NoSQL数据库产品,具有基于用户的强大安全性,使存储,同步和查询数据非常容易。 用户界面也非常直观,因此很容易将头放在如何最好地构造数据上。

入门 (Getting Started)

You must first create a new Firebase project (or use an existing one) and find your Firebase config object that would be needed in your React environment.

您必须首先创建一个新的Firebase项目 (或使用现有项目 )并找到React环境中所需的Firebase配置对象。

Note that it’s also important to set up authentication when using Firestore in your projects to limit access to your database, this will become important a little later in this article. I have outlined how to set up a new Firebase project that handles authentication in React in a previous article which you can follow.

请注意,在您的项目中使用Firestore来限制对数据库的访问时,设置身份验证也很重要,这在本文稍后会变得很重要。 我已经在上一篇文章中概述了如何在React中设置一个新的Firebase项目来处理身份验证,您可以遵循。

Once your project has been set up and connected to your React application with authentication ready, you may start using Cloud Firestore by navigating your “Database” in the Firebase console. You will then be prompted to follow the database creation flow and be asked to select a starting mode for your Cloud Firestore Security Rules.

设置好项目并通过身份验证就绪将其连接到React应用程序后,您可以通过在Firebase控制台中导航“数据库”来开始使用Cloud Firestore。 然后,系统将提示您遵循数据库创建流程,并要求您为Cloud Firestore安全规则选择启动模式。

I typically start in locked mode, then modify the rules to allow anyone to read the data and only authenticated users to write to it.

我通常从锁定模式开始,然后修改规则,以允许任何人读取数据,仅允许经过身份验证的用户写入数据。

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read
allow write: if request.auth != null;
}
}
}

This will be progressively fine-tuned as we move along but this is good enough as a starting point for most projects. I tend to start in “locked mode” to avoid ever forgetting to tighten the security settings before publishing any project. I’d rather loosen security if needed than have to remember to tighten it.

随着我们的前进,这将逐渐进行微调,但这足以作为大多数项目的起点。 我倾向于从“锁定模式”开始,以避免在发布任何项目之前忘记收紧安全设置。 我宁愿在需要时放宽安全性,也不必记住加强安全性。

The next thing I think about is how I’d like to structure the database. This is important because depending on how the application — and it’s data — grows, scalability becomes a concern. We don’t want to suffer slower data retrieval because our database was not structured properly.

我接下来要考虑的是如何构造数据库。 这很重要,因为取决于应用程序及其数据的增长方式,可伸缩性成为一个问题。 我们不希望数据检索速度变慢,因为我们的数据库结构不正确。

Take a look at the docs to read about the different options and weigh the pros and cons of each approach.

查看文档以了解不同的选择,并权衡每种方法的利弊。

For Burger Builder, I separated the menu from the orders, with each user grouped under the orders collection.

对于Burger Builder,我将菜单与订单分开,每个用户都分组在订单集合下。

Image for post
menu for menu, orders to group users
菜单菜单,对用户分组的命令

创建一些汉堡 (Create some burgers)

For this project, only 3 pieces of information matter to me for each burger; the ingredients, the price, and the name of the burger. When setting up the menu, these would be all I need.

对于这个项目,每个汉堡只有3条信息对我很重要; 汉堡的成分,价格和名称。 设置菜单时,这些便是我所需要的。

import app from "firebase/app";
import "firebase/firestore"this.db = app.firestore();createBurger = (ingredients, name, price) =>
this.db.collection("menu").doc(name).set({
ingredients,
name,
price,
});

Instead of letting Firebase auto-set a doc id for me, I’m giving it the name of the burger. It might make it easier for me to find and update or delete burger information later on.

我没有让Firebase为我自动设置文档ID,而是给它起了汉堡的名字。 以后,它可能会使我更容易找到和更新或删除汉堡信息。

Note that I’m using set to push data up to Firestore; this creates a new doc in the menu collection if there isn’t one with the same name already. If the doc already exists, it would overwrite it. As stated in the docs, if you’re not sure whether the document exists, pass the option to merge the new data with any existing document to avoid overwriting entire documents.

请注意,我正在使用set将数据推送到Firestore。 如果还没有相同name文档,则会在menu集合中创建一个新文档。 如果该文档已经存在,它将覆盖它。 如docs中所述,如果不确定文档是否存在,请传递选项以merge新数据与任何现有文档merge ,以避免覆盖整个文档。

createBurger = (ingredients, name, price) =>
this.db.collection("menu").doc(name).set({
ingredients,
name,
price,
}, { merge: true });

There’s one last thing I’d like to mention before moving on to pulling data down. I only want an administrator to be able to upload menu items. Our current Cloud Firestore Security Rules set is not good enough because it currently allows any authenticated user to write to the database.

在继续提取数据之前,我要说的最后一件事。 我只希望管理员能够上载菜单项。 我们当前的Cloud Firestore安全规则集还不够好,因为它当前允许任何经过身份验证的用户写入数据库。

We can change that by allowing anyone to read the menu but only the admin to write to it and allow only authenticated users to read and write to orders. This is a simple case because I only need one account to have “admin” access, so I can get away with using their uid to grant access.

我们可以通过允许任何人读取菜单,但只有管理员可以写入菜单,并且仅允许经过身份验证的用户读取和写入订单,来更改此菜单。 这是一个简单的情况,因为我只需要一个帐户即可拥有“管理员”访问权限,因此我可以摆脱使用其uid授予访问权限的uid

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /menu/{document=**} {
allow read
allow write: if request.auth != null && request.auth.uid == "[admin uid]"
}
match /orders/{document=**} {
allow read, write: if request.auth != null
}
}
}

订购汉堡 (Order a Burger)

Since we already allow read access to the menu for anyone, we can simply make a get request on the menu document to pull down all the available menu options.

由于我们已经允许任何人对菜单进行读取访问,因此我们可以简单地在menu文档上发出get请求,以下拉所有可用的菜单选项。

props.firebase.fetchBurgers comes from firebase.js

props.firebase.fetchBurgers来自firebase.js

import app from "firebase/app";
import "firebase/firestore"this.db = app.firestore();fetchBurgers = () => this.db.collection("menu").get();

When fetching data like this, Cloud Firestore will order the result by creation descending— the way it’s ordered in your Firebase console. You can choose how you’d like to order the data with orderBy, limit how many you want to fetch with limit and query for specific kinds of data with where.

像这样获取数据时,Cloud Firestore将按创建降序对结果进行排序(即在Firebase控制台中进行排序的方式)。 你可以选择你想如何排序的数据orderBy ,限制你要多少有获取limit和查询特定类型的数据与where

const burgersRef = db.collection("menu");burgersRef.where("price" < 10").orderBy("price").limit(2)

One thing to note about using orderBy and where in the same query is that if you include a filter with a range comparison (<, <=, >, >=), your first ordering must be on the same field. So you cannot do something like:

关于使用orderBy以及在同一查询中的where要注意的一件事是, 如果您包含具有范围比较的过滤器( < <= > >= ),则您的第一次排序必须在同一字段上 。 因此,您不能执行以下操作:

burgersRef.where("price" < 10").orderBy("name").limit(2)

下订单 (Place an Order)

The structure for orders is a bit different; they are grouped by the currently logged in user’s UID — unique identifier. Under each user, there’s another grouping because each user could have more than one order. Each user’s order is grouped by the timestamp of that order. This type of sub-grouping is made easy with the Firestore subcollection structuring pattern.

订单的结构略有不同; 它们按当前登录的用户的UID(唯一标识符)分组。 在每个用户下,还有另一个分组,因为每个用户可能有多个订单。 每个用户的订单按该订单的时间戳分组。 使用Firestore子集合结构化模式可以轻松实现这种子分组。

In the end, my database structure for a user’s orders looks like this:

最后,我的用户订单数据库结构如下:

/orders/[uuid]/order/[timestamp]
Image for post
an “other” group could also be created for users that have not yet signed up
还可以为尚未注册的用户创建一个“其他”组

To push data this way, we first need to know the currently signed-in user. This is easy to find because we only have one Firebase instance running.

要以这种方式推送数据,我们首先需要知道当前登录的用户。 这很容易找到,因为我们只有一个Firebase实例正在运行。

getCurrentUser = () => this.auth.currentUser;

On the user-facing side, I implemented a very basic add-to-cart functionality where users can click an item on the menu, select a quantity, and add that to the cart. When satisfied, clicking “Place Order” will push the cart items as well as the grand total up to Firebase. The code behind this is in the Burger Builder Github repo.

在面向用户方面,我实现了一个非常基本的购物车添加功能,用户可以单击菜单上的一项,选择一个数量,然后将其添加到购物车中。 满意后,单击“下订单”将购物车中的物品以及总计金额推送到Firebase。 其背后的代码在Burger Builder Github存储库中。

Image for post
add or remove items to update the cart
添加或删除项目以更新购物车
Image for post
validate and publish to Firebase
验证并发布到Firebase

Since we’re grouping orders by users, the Firebase call has to be reflected accordingly:

由于我们是按用户对订单进行分组,因此必须相应反映Firebase调用:

import app from "firebase/app";
import "firebase/firestore"this.db = app.firestore();placeOrder = (order, uuid) => {
const d = app.firestore.Timestamp.fromDate(new Date()).seconds.toString(); return this.db
.collection("orders")
.doc(uuid)
.collection("order")
.doc(d) //- d needs to be a string
.set(order);
}

The component will then supply the order and uuid. On “Place Order” click:

然后,组件将提供orderuuid 。 在“下订单”上,单击:

const placeOrder = () => {
const uuid = props.firebase.getCurrentUser().uid;
const grandTotal = cart.reduce((acc, curr) => acc + curr.total, 0);
const order = { cart, grandTotal }; props.firebase.placeOrder(order, uuid)
.then(() => console.log("Sucessfully written to doc!"))
.catch((err) => console.log("Something went wrong!", err));
};

Note: array.reduce is a really cool ES6 method that executes a reducer function (that you provide) on each element of an array, resulting in single output value.

注意array.reduce是一个非常酷的ES6方法,它对数组的每个元素执行reducer函数(由您提供),从而产生单个输出值。

查看您的订单历史记录 (View your Order History)

Fetching a user’s orders is similar to fetchBurger but with an added complexity. As stated earlier, this is because we’ve grouped a user’s orders by when they placed the order.

提取用户的订单类似于fetchBurger但是增加了复杂性。 如前所述,这是因为我们已经按照用户下订单的时间对他们的订单进行了分组。

fetchOrders = (uuid) => this.db.collection("orders").doc(uuid).collection("order").get();

The fetch call with useEffect is also very similar to what was used to fetch the menu items. The difference in this case comes mostly in the user interface.

使用useEffect的fetch调用也非常类似于用来获取菜单项的调用。 这种情况下的区别主要在于用户界面。

Image for post
bare minimum
最低限度

We need to update our Cloud Firestore Security Ruleset one last time. We should make it so that if another user was created and they tried to see another user’s previous orders, they’d get blocked by Firebase (it’s always to a good idea to display things in the UI prettily; no more white pages!). We only want people to be able to see their own data, not anyone else’s:

我们需要最后一次更新Cloud Firestore安全规则集。 我们应该这样做,以便如果创建了另一个用户,并且他们试图查看另一个用户的先前订单,则它们将被Firebase阻止(最好在UI中简洁地显示内容;不再需要白页!)。 我们只希望人们能够看到自己的数据,而不希望其他人看到的数据:

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /menu/{document=**} {
allow read
allow write: if request.auth != null && request.auth.uid == "..."
}
match /orders/{userId}/{document=**} {
allow read, write: if request.auth != null && request.auth.uid == userId
}
}
}

The expression userId allows the variable userId to be used when setting the rules. This means that {userId} in /orders/{userId} needs to match the user’s UID.

表达式userId允许在设置规则时使用变量userId 。 这意味着{userId}/orders/{userId}需要匹配用户的UID。

结论 (Conclusion)

This article and the related repo are intended mostly for demonstration purposes. So much more can be done to improve the project and fix potential bugs, so feel free!

本文和相关的回购协议主要用于演示目的。 可以做很多事情来改善项目并修复潜在的错误,所以请放心!

One example of such is allowing users to change the quantity directly in the cart instead of them having to find the burger in the menu and changing it from there. There’s also currently no way to completely remove an item from the cart once it’s been added.

这样的一个例子是允许用户直接在购物车中更改数量,而不必在菜单中找到汉堡并从那里更改。 添加商品后,目前还无法从购物车中完全删除商品。

As far as Firebase and Cloud Firestore goes, this is enough to get you started and help smooth out common questions. The Firebase docs are pretty exhaustive and should have a solution to any other issues that might arise. Also, check out my Github profile for more projects like this.

就Firebase和Cloud Firestore而言,这足以让您入门并帮助解决常见问题。 Firebase文档非常详尽,应针对可能出现的任何其他问题提供解决方案。 另外,请查看我的Github个人资料以获取更多类似这样的项目。

翻译自: https://medium.com/swlh/setup-a-database-in-react-with-firebase-cloud-firestore-110bbf18cd86

firebase创建数据库

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值