我从使用Firebase实时数据库中学到的东西

I began using Firebase Realtime database right at the end of my Final Year of College at a time when a good working project could save you from a lifetime of issues with your Supervisors and Academic board. I had been working on an Android Java project and thus needed a Backend for my project. Looking at the timeline involved, a friend recommended Firebase to me. Since I needed a backend that could manage an all required inclusive tool such as authentication, hosting, storage and at the same time providing a great database structure to store my data, I decided to opt-out of the MySQL world at the time which with its several experienced programmers and went into this new JSON based tool presented by Google.

我在大学期末毕业时就开始使用Firebase Realtime数据库,当时一个好的工作项目可以使您免于一生中与主管和学术委员会有关的问题。 我一直在从事Android Java项目的工作,因此我的项目需要后端。 看着所涉及的时间表,一个朋友向我推荐了Firebase。 由于我需要一个可以管理所有必需的包容性工具(例如身份验证,托管,存储)的后端,并同时提供强大的数据库结构来存储我的数据,因此我决定退出MySQL世界,它的几个经验丰富的程序员,并加入了Google提供的基于JSON的新工具。

As a new tool, it was not long before I experienced, the harm of being a first-time user. From countless nights of seeing no results to figuring out ways of making simple queries which would have taken just a few minutes using other database systems, I undertook a journey of pain and stress as experienced by most programmers on their path to explore a new tool and leverage it to the max. This article is thus for anyone who is on the beginning path of using Firebase. Although Google has moved on and made this tool even better with several versions each year and new ways of implementations and improvements such as the inclusion of Firestore, its new scalable Database, and others, Firebase Realtime Database is still used by the majority of Android Programmers due to its tried years of use. It is important for the beginner to understand how this tool works in order not to make assumptions that are brought from using another Database. This article with codes written in Android Java has thus been written to enlist what I learned on the path to discovering what and what not to do in attempting to use Firebase in building Mobile Applications.

作为一种新工具,不久之后我就体验了成为首次用户的危害。 从无数次无结果的夜晚到找出使用其他数据库系统仅需几分钟的简单查询方法,我就经历了大多数程序员在探索新工具和新途径时所经历的痛苦和压力。发挥最大作用 因此,本文适用于使用Firebase的入门人员。 尽管Google每年都在不断改进该工具,并提供了多个版本,并且采用了新的实现方式和改进方式,例如包括Firestore ,其新的可扩展数据库等,但大多数Android程序员仍在使用Firebase Realtime Database。由于其多年的使用经验。 对于初学者来说,重要的是要了解此工具的工作方式,以免做出使用其他数据库带来的假设。 因此,用Android Java编写的代码写这篇文章是为了列举我在尝试使用Firebase构建移动应用程序时发现什么以及不该做什么的过程中所学到的东西。

It is an Asynchronous API

这是一个异步API

First of all, it is important for the beginner to understand that Firebase is an asynchronous API since it makes use of the HTTP client protocol which is synchronous in the sense that every request will get a response but asynchronous in the sense that response takes a long time and multiple operations can be run in parallel. This means that response from your Firebase server may take a long time to load on your screen and although everything may well be put in place, sometimes your application may seem not to respond due to this short time drag. It is also easy for your request to not appear on your screen for some period of time. Again, it is easy for you to miss values if the right implementation is not done. For instance, in the following code, we attempt to bind a Firebase request to our Viewholders.

首先,对于初学者来说重要的是要了解Firebase是异步API,因为它使用了HTTP 客户端协议 ,从每个请求都会得到响应的角度来说,它是同步的,而从响应需要很长时间的角度来看,则是异步的时间和多个操作可以并行运行。 这意味着您的Firebase服务器的响应可能需要很长时间才能加载到屏幕上,并且尽管一切都准备就绪,但有时由于拖曳时间短,您的应用程序似乎没有响应。 您的请求有时也不会出现在屏幕上也很容易。 同样,如果没有正确执行,很容易错过值。 例如,在以下代码中,我们尝试将Firebase请求绑定到我们的Viewholder。

String name;
String productnames;
String productnamesinsnapshot;
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView((R.layout.productactivity));
productnames = "";
}
@Overridepublic int getItemCount() {return super.getItemCount();
}
@Overrideprotected void onBindViewHolder(@Nullable final ViewHolder holder, int position, @Nullable Products model) {if (model != null) {
name = "Hand Bag";
pid = "M3WgbcMJRrIUK6RMS7";
holder.productsname.setText(name);
Log.d(TAG, " BeforeProductName " + name);
FirebaseDatabase myfirebaseDatabase;
myfirebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference Products;
Products = myfirebaseDatabase.getReference().child("Products");
Products.keepSynced(true);
Query firebasequery =
Products.orderByChild("pid").equalTo(pid);
firebasequery.addValueEventListener(new ValueEventListener() {
@Overridepublic void onDataChange(DataSnapshot dataSnapshot) {for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {if (dataSnapshot1.child("name").getValue() != null) {
productnamesinsnapshot = dataSnapshot1.child("name").getValue(String.class);
holder.productsname.setText(productnames);
Log.d(TAG, "AtProductName " + productnamesinsnapshot);
}
}
}
@Overridepublic void onCancelled(DatabaseError databaseError) {
}
});
holder.productsname.setText(productnames);
Log.d(TAG, "AfterProductName" + productnamesinsnapshot);

The log results for this will be

日志结果将是

D/Google Activity: BeforeProductName Hand Bag
D/Google Activity: AfterProductName null
D/Google Activity: AtProductName Hand Bag

It is easy for one to assume that since productnamesinsnapshot is accessed publicly, it should populate the Viewholder since it is already set in at the ValueEventListener, but this is where the understanding of Asynchronous APIs comes in handy. Because the database attempts to make operations even when operations have not been received, it obtains the value from the ValueEventListener but since it has not received the value yet, it proceeds with the rest of the operation, thus productnamesinsnapshot remains empty. When set to the last holder, it does not populate and renders null. Later the value is received and binds to the second holder with value logged at “AtProductName”.After several attempts at testing frustratingly, I figured it out.

容易假设,由于productnamesinsnapshot是公开访问的,因此应该填充Viewholder,因为已经在ValueEventListener中设置了Viewholder,但这对理解异步API很有用。 因为即使在未接收到操作的情况下数据库也会尝试执行操作,所以它从ValueEventListener获取值,但是由于尚未接收到该值,因此它将继续执行其余操作,因此productnamesinsnapshot保持为空。 设置为最后一个持有人时,它不会填充并呈现null。 后来接收到该值,并将其绑定到第二个持有人,并将值记录在“ AtProductName”上。经过几次令人沮丧的测试,我终于找到了答案。

I learned surprisingly here that values outside the Firebase Request are not publicly available hence the need for Callbacks and other implementations before using those values in any part of your Activity. One way was to make all the operations in the OnDataChange() method and so the Viewholder, holder, as seen in the example, was not set outside the ValueEventListener but rather in the OnDataChange() method. This small difference could save you lots of time if you try it that way. Trust me I found out late. This article here provides the best resource online for understanding and solving this issue.

我在这里惊奇地了解到,Firebase Request之外的值没有公开可用,因此在Activity的任何部分中使用这些值之前,都需要回调和其他实现。 一种方法是在OnDataChange()方法中进行所有操作,因此,如示例中所示,Viewholder持有者不是在ValueEventListener之外设置的,而是在OnDataChange()方法中设置的。 如果您尝试这种小差异,则可以节省大量时间。 相信我,我发现晚了。 本文在此处提供了用于理解和解决此问题的最佳在线资源。

It Is Can Be Hard To Retrieve From Nested Nodes

从嵌套节点检索可能很困难

At the first look, Firebase looks very simple. Just pulling values from a list of JSON tree structure and following a sequence of paths to make retrieval, with some key pair values. The Database structure could also seem simple but could end up one of the biggest surprises. Most of the Firebase Documentation normally deals with retrieving values from one node, usually the root node of the database. But practically implementations are more complex than that. Retrieving from child nodes could be a great issue if an understanding is not seen from the way a Firebase sees differently from the way you see it. Let’s check this Firebase Tree Structure:

乍一看,Firebase看起来非常简单。 只需从JSON树结构列表中提取值,然后按照一系列路径进行检索即可,并带有一些密钥对值。 数据库结构看起来也很简单,但最终可能会成为最大的意外之一。 大多数Firebase文档通常都处理从一个节点(通常是数据库的根节点)检索值的问题。 但是实际上,实现要比这复杂得多。 如果从Firebase的观察方式与您的观察方式看不到理解,则从子节点检索可能是个大问题。 让我们检查一下Firebase树结构:

Retrieving values from this structure means moving to each node at a time. This is where the terminologies come into play. Words like Snapshot, Key could mess up and I needed to figure out what each means. I realized to my great excitement that regularly checking your logs to know precisely what it is retrieving could help prevent assumptions from what you think the Database should and must retrieve. For every node you reference, it retrieves all the child nodes from that reference point.

从此结构检索值意味着一次移动到每个节点。 这就是术语起作用的地方。 诸如Snapshot,Key之类的词可能会弄乱,我需要弄清楚它们的含义。 我非常兴奋地意识到,定期检查您的日志以准确知道它正在检索什么,可以帮助防止您认为数据库应该而且必须检索的假设。 对于您参考的每个节点,它将从该参考点检索所有子节点。

For instance, using the parseSnaphot along with the Firebaseadapter to retrieve values from our database:

例如,使用parseSnaphot和Firebaseadapter来从我们的数据库中检索值:

String traderuser = "qqKFb5Jag5asMUVFWU2DQUc8fSL1qqKFb5Jag5asMUVFWU2DQUc8fSL1";
String userID = "qqKFb5Jag5asMUVFWU2DQUc8fSL1";
Query queryhere =
FirebaseDatabase.getInstance().getReference().child("Orders").orderByChild("traderuser").equalTo(traderoruser);
Query previoususerorderquery = queryhere.getRef().orderByChild("uid").equalTo(userID);if (previoususerorderquery != null) {
FirebaseRecyclerOptions<Order> options =new FirebaseRecyclerOptions.Builder< Order >().setQuery(previoususerorderquery, new SnapshotParser< Order>() {
@Nullable
@Overridepublic Order parseSnapshot(@Nullable DataSnapshot snapshot) {
Log.i(TAG, "Admin New Customers " + snapshot);if (snapshot.child("orderkey").getValue(String.class) != null) {
orderkey = snapshot.child("orderkey").getValue(String.class);
}if (snapshot.child("name").getValue(String.class) != null) {
name = snapshot.child("name").getValue(String.class);
}return new Order (orderkey, name);
}
}).build();

We can, therefore, retrieve values from this Database using this structure

因此,我们可以使用此结构从该数据库检索值

snapshot.child("name").getValue(String.class);

The easy method may create an easy assumption for the beginner until he begins to go deeper into the node. From the previous example, the routine for retrieving values for products may be:

简单方法可以为初学者创建一个简单的假设,直到他开始更深入地研究节点。 从前面的示例中,检索产品值的例程可能是:

snapshot.child("products").child("pid").getValue(String.class);

This is a wrong attempt since Firebase begins from snapshot, Firebase loops to each node in a step by step order and thus several nodes have been missed in this attempt. A request may return null when trying to thus retrieve values from the products node.

由于Firebase从快照开始,所以Firebase是错误的尝试,Firebase会逐步地循环到每个节点,因此此尝试中错过了几个节点。 当尝试从产品节点检索值时,请求可能返回null

Let us create a new retrieval means to understand it better. First, let’s check up this example here.

让我们创建一种新的检索方式以更好地理解它。 首先,让我们在这里检查该示例。

@Nullable  Query queryhere =                     FirebaseDatabase.getInstance().getReference().child("Orders").orderByChild("traderuser").equalTo(traderuser);if (queryhere != null) {FirebaseRecyclerOptions<Order> options =new FirebaseRecyclerOptions.Builder< Order >()
.setQuery(queryhere, new SnapshotParser< Order >() {
@Nullable @Override public Order parseSnapshot(@Nullable DataSnapshot snapshot) {
snapshotkeys = snapshot.getKey();
Log.d("SNAPshotkey", snapshotkeys);for (DataSnapshot snapshot1 : snapshot.getChildren()) {
secondsnapshotkey = snapshot1.getKey();
Log.d("SNAPSHOTKEYS", secondsnapshotkey);for (DataSnapshot snapshot2 : snapshot1.getChildren()) {
thirdsnapshotkey = snapshot2.getKey();
Log.d("THIRDSNAPSHOTKEYS", thirdsnapshotkey);if (snapshotkeys != null) {if (secondsnapshotkey != null) {if (thirdsnapshotkey != null) {if(snapshot.child("products").child(thirdsnapshotkey).child("image").getValue() != null) { image = snapshot.child("products").child(thirdsnapshotkey).child("image").getValue(String.class);
}if (snapshot.child("products").child(thirdsnapshotkey).child("name").getValue() != null) {
name = snapshot.child("products").child(thirdsnapshotkey).child("name").getValue(String.class);
}
}
}
}
}
}return new Order (image, name);
}
}).build();

We keep looping through the nodes. From each snapshot, we can see the key we retrieved by calling the getKey() method. Here are a few logs to understand what happens when we call for the keys for each snapshot to be displayed.

我们不断循环遍历节点。 从每个快照中 ,我们可以通过调用get Key()方法来查看检索到的密钥 。 以下是一些日志,以了解当我们要求显示每个快照的键时会发生什么。

D/SNAPshotkey: -Lyyv6smOjUFylfUSnho
D/SNAPSHOTKEYS: address
D/SNAPSHOTKEYS: amount
D/SNAPSHOTKEYS: city
D/THIRDSNAPSHOTKEYS: ASAHSGDSKHGGKJDSFHHKJDGHKJKDS
D/SNAPSHOTKEYS: products
D/THIRDSNAPSHOTKEYS: ADHDLKHDLKHLKDHKJHDKHKFDKHFDKLHDFKJHF

Hence from example two, notice in our attempt to get the values in the product node, we actually jumped from using snapshot1.getKey() to using snapshot2.getKey() before calling on pid. In fact, snapshot1.getKey() is actually products as shown in the log. So, in traversing the node, we can imagine us making a rewrite of our attempt as:

因此,从示例二中,请注意,在尝试获取product节点中的值时,实际上是在调用pid之前,从使用snapshot1.getKey()跳转到使用snapshot2.getKey() 实际上, snapshot1.getKey()实际上是产品 ,如日志中所示。 因此,在遍历节点时,我们可以想象我们将尝试重写为:

FirebaseDatabase.getInstance().getReference().child("Orders").child(snapshot.getKey()).child(snapshot1.getKey()).child(snapshot2.getKey()).child("image");

Hence the same way we see in retrieving that value we see. This breakdown made this whole technical stuff way simple!

因此,我们在检索该值时所看到的方式相同。 此故障使整个技术资料变得简单!

if(snapshot.child("products").child(thirdsnapshotkey).child("image").getValue() != null) {                                                         
image = snapshot.child("products").child(thirdsnapshotkey).child("image").getValue(String.class);
}

The Models Must Follow All Required Rules

模型必须遵循所有必需的规则

Models may look that innocent, but I learned that it is very important for one to avoid many problems that come along with Models in Firebase. Model Classes interface with your Firebase Database and as such provide a sort of Key Pair structure to retrieve the information unto your Database.

模型看似天真无邪,但我了解到,避免Firebase中的模型带来的许多问题对我来说非常重要。 模型类与Firebase数据库进行交互,因此提供了一种“密钥对”结构来检索数据库中的信息。

Let’s look at this example Model Class:

让我们看一下这个示例模型类:

public class Order {private String desc, image, name;public Cart() {
}public Order (
String desc, String image, String name;
) {this.desc = desc;this.image = image;this.name = name;
}public String getdesc () {return desc;
}public void setdesc (String desc) {this.desc = desc;
}public String getimage () {return image;
}public void setimage (String image) {this.image = image;
}public String getname () {return name;
}public void setname (String name) {this.name = name;
}
}

Taking our Sample Model Class for instance there are some few things to note well.

以我们的样本模型类为例,有几点需要注意。

Have an empty constructor: Make sure you call an empty constructor. Not calling an empty constructor could prove the difference between your happy working and a late-night sleep.

有一个空的构造函数:确保调用一个空的构造函数。 不调用空的构造函数可以证明您的工作愉快与深夜睡眠之间的区别。

Same name: Although it may look extremely simple and has been specified in many documentations, it is easy to miss this. Your data will not be fetched if the name of your variables does not correspond with the names specified in your Firebase. Make sure the names are consistent. For instance, image is the same as image in our Firebase Database. In fact think of it simply as whatever names are in my Database Tree is going to be the same in my Model class as well, Capiche?

同名:尽管它看起来非常简单并且已在许多文档中进行了指定,但很容易错过这一点。 如果变量名称与Firebase中指定的名称不匹配,则不会获取您的数据。 确保名称一致。 例如, 图像与Firebase数据库中的图像相同。 实际上,简单地想一下,因为数据库树中的任何名称在Model类中也将相同,Capiche?

Now let’s check this Firebase Realtime Database tree here:

现在,让我们在这里检查此Firebase实时数据库树:

Image for post
Image showing numerical values inputted as strings in Firebase
该图显示了在Firebase中作为字符串输入的数值

Do not retrieve the value from Non-Value Nodes: It took me missing a vital hackathon to realize this important thing. When calling from your Model Class avoid adding the name of your Nodes. Firebase does not see it as a point to retrieve values but a place to retrieve a tree of values also known as Hashmap. The best practice is to have, for instance, in this example a string called one. Having a string variable inside your Model Class called “l” could be a problem since the information could be retrieved as a Hashmap and cannot be converted in the way you do not want it, if, for instance, you want to just retrieve a string value.

不要从非价值节点中获取价值:我错过了一次重要的黑客马拉松,以实现这一重要目标。 从模型类调用时,避免添加节点的名称。 Firebase不会将其视为检索值的点,而是将其检索值树(也称为Hashmap)的地方 。 最佳实践是,例如,在此示例中,使用一个名为one的字符串。 在模型类中将一个字符串变量称为“ l”可能是一个问题,因为该信息可以作为Hashmap检索,并且不能以您不希望的方式进行转换,例如,如果您只想检索一个字符串值。

The “Cannot Convert Object of Type String to HashMap Error” could cause you a lot of sleepless nights.

“无法将字符串类型的对象转换为HashMap错误”可能会导致您不眠之夜。

You Must Be Sure Of Your Input Values

您必须确定您的输入值

For numbers make sure that to avoid having double quotes if you are dealing with numerical figures. Sometimes the value type of what is on your client-side may be different from the value specified in Firebase. I recommend making every number into a string value inside your Firebase Database with double quotes as seen in the previous Firebase Database Tree and manipulating the value in your Android Code with the Integer.parse(value) in Java or whatever language you will like to write in.

对于数字,如果要处理数字,请确保避免使用双引号。 有时,客户端的值的类型可能与Firebase中指定的值不同。 我建议将每个数字转换为Firebase数据库中带双引号的字符串值(如先前的Firebase数据库树中所示) ,并使用Java或您要编写的任何语言使用Integer.parse(value)来处理Android代码中的在。

Normalization Makes Your Structure Simple And Easy To Deal With

规范化使您的结构简单易用

Countless to say Normalization of your database is so important if you want to avoid several frustrations when retrieving values and also avoid several database complexities as your Database grows with time. Also speed retrieval is also thus important. Many recommendations as to the best practices are specified in https://howtofirebase.com/firebase-data-modeling-939585ade7f4 as well as the means of optimization.

不用说,如果您希望避免在获取值时遇到一些挫败感,并且随着数据库随着时间的增长而避免多种数据库的复杂性,那么数据库的规范化就非常重要。 因此,速度检索也很重要。 https://howtofirebase.com/firebase-data-modeling-939585ade7f4中指定了许多有关最佳做法的建议以及优化方法。

Listeners and Adapters must be well Handled:

侦听器和适配器必须正确处理

Firebase is an API with a lot of Listeners, listening to calls to understand changes and respond to them. One of the ways Listeners are very important is in the authentication. Make sure to understand the best way to authenticate. Also, in attaching adapters such as Recyclerview it is important to know the best way. I have created a simple means to make sure the reader understands the best way to work with listeners.

Firebase是具有许多侦听器的API,它们侦听调用以了解更改并做出响应。 侦听器非常重要的一种方式是身份验证。 确保了解最好的身份验证方法。 另外,在连接诸如Recyclerview之类的适配器时,了解最佳方法也很重要。 我创建了一种简单的方法来确保读者理解与收听者合作的最佳方式。

1. First, make your adapter public as well as anything you may need to access publicly

1.首先,公开您的适配器以及您可能需要公开访问的所有内容

public FirebaseRecyclerAdapter adapter;
RecyclerView recyclerView;
FirebaseAuth mAuth;
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView((R.layout.activity_home));

2. Set your Firebase Adapter Layouts

2.设置您的Firebase适配器布局

recyclerView = findViewById(R.id.recycler_menu);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);if (recyclerView != null) {
recyclerView.setLayoutManager(layoutManager);
}

3. Get your instance of your Firebase Authenticator in your OnCreate() Method

3.在OnCreate()方法中获取Firebase Authenticator的实例

mAuth = FirebaseAuth.getInstance();

4. Make sure you deal with every Firebase call before you bring in your adapter;

4.引入适配器之前,请确保您处理了每个Firebase调用;

FirebaseDatabase myfirebaseDatabase = irebaseDatabase.getInstance();
DatabaseReference myProducts= myfirebaseDatabase.getReference().child("Product");

5. Your adapter procedures could all be bundled up as a function called fetch() and called in your OnCreate() method

5.您的适配器过程可以全部捆绑为一个名为fetch()的函数,并在您的OnCreate()方法中调用

fetch();
recyclerView.setAdapter(adapter);

6. As shown in 5, set the adapter immediately after, binding your FirebaseAdapter immediately to your recyclerview.

6.如图5所示,在设置适配器之后,立即将FirebaseAdapter绑定到recyclerview。

Now in dealing with your listeners, make sure to call them in the onStart() method, hence your application will start listening immediately the application begins to call.

现在,在处理您的侦听器时,请确保在onStart()方法中对其进行调用,因此您的应用程序将立即开始侦听该应用程序,以开始对其进行调用。

@Overrideprotected void onStart() {super.onStart();
firebaseAuthListener = new FirebaseAuth.AuthStateListener() {
@Overridepublic void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
user = mAuth.getCurrentUser();if (mAuth != null) {if (user != null) {
traderoruser = user.getUid();
}
}
} };if (mAuth != null) {
mAuth.addAuthStateListener(firebaseAuthListener);
}if (adapter != null) {
adapter.startListening();
}
}

7. Now with all the right sequence, your app will listen to Firebase, you can also read more on Firebase Listeners and Firebaseadapters to fully comprehend the best way to manipulate it, else you can be left with a blank screen since maybe you seem to jump some vital steps each time. Don't worry you will be just fine!

7.现在,按照正确的顺序进行操作,您的应用程序将收听Firebase,还可以在Firebase Listeners和Firebaseadapters上阅读更多内容,以充分理解最佳的操作方式,否则,您可能会空白,因为您似乎每次都跳一些重要步骤。 别担心,你会很好的!

Check your Firebase Versions Carefully:

仔细检查您的Firebase版本:

Make sure to check the version of the Firebase version you are using to know what is the best implementation method. Most documentation follows after a particular version which is updated periodically. So don't be shocked that the amazing YouTube tutorial did not work exactly the way you wanted it to end up!

确保检查您正在使用的Firebase版本的版本,以了解最佳的实现方法。 大多数文档都在特定版本之后发布,该特定版本会定期更新。 因此,不要惊异惊人的YouTube教程并不能完全按照您希望的方式运行!

Index your Database as Database grows:

随着数据库的增长对数据库进行索引:

Indexing your database helps Firebase to easily retrieve your Database so always make sure to index your Database. Indexing is best explained here.

对数据库建立索引有助于Firebase轻松检索数据库,因此请务必确保对数据库进行索引。 最好在这里解释索引。

Multiple Queries Could Prove A Big Hack!

多个查询可能证明是一个大骗局!

Image for post
Firebase RealTime Database structure with traderuser used here for a unique index for multiple queries
带有traderuser的Firebase RealTime数据库结构在这里用于多个查询的唯一索引

Finally, be aware of the restriction in writing multiple queries in Firebase Realtime Database. It has certain limitations as compared with Firestore, as shown in https://firebase.google.com/docs/database/rtdb-vs-firestore and thus multiple queries at a time could result in an error. It is thus important to create a unique index in your database. Even trying to sort in descending could feel like rocket science if you don't get the information needed. So let’s see. This is what I learned. In trying to query for multiple query clauses to retrieve tid and uid, we create a unique index of traderuser which contains the two values, thus enabling us to make an effective order. As seen in this query.

最后,请注意在Firebase Realtime数据库中编写多个查询的限制。 与Firestore相比,它具有某些局限性,如https://firebase.google.com/docs/database/rtdb-vs-firestore中所示,因此一次进行多个查询可能会导致错误。 因此,在数据库中创建唯一索引很重要。 如果您没有获得所需的信息,即使尝试按降序进行排序也可能会感觉像火箭科学。 让我们来看看。 这是我学到的。 在尝试查询多个查询子句以检索tid时 uid 我们创建一个包含两个值的traderuser唯一索引,从而使我们能够制定有效的订单。 如该查询所示。

Query queryhere =
FirebaseDatabase.getInstance().getReference().child("Orders").orderByChild("traderuser").equalTo(traderuser);

With this unique index, you can query for multiple values where it would have been just simple with somewhere clauses somewhere. Anyway, an improvement has been made with Firestore and hence these queries have become way easier.

有了这个唯一索引,您可以查询多个值,而在某些地方的where子句本来就很简单。 无论如何,Firestore进行了改进,因此这些查询变得更加容易。

Conclusion: Using Firebase can sometimes prove a challenge, but understanding how it works enables you to leverage its powerful tools in creating an enterprise application that can help leverage other Google-based platforms and enable your business to accelerate as you get acquainted with its features and with its internal mechanism, whether on Web or on Mobile. You have what it takes but like they always say, “experience is the best teacher”. Happy Firebase Realtime Experience!

结论:使用Firebase有时可能会遇到挑战,但是了解Firebase的工作原理可以使您利用其强大的工具来创建企业应用程序,从而可以利用其他基于Google的平台,并使您的业务在熟悉其功能和特性后得以加速发展其内部机制,无论是在Web上还是在移动设备上。 您有所需要的东西,但就像他们总是说的那样,“经验是最好的老师”。 快乐的Firebase实时体验!

翻译自: https://medium.com/@peeman34/what-i-learned-from-using-firebase-realtime-database-ff48c7eb49fa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值