简体   繁体   中英

Searching a firebase database

Preface:

For this question to make sense, I need to describe my intent for the database. It will be used to store user data based on a grid of latitude and longitude sectors created by finding the floor value of the exact coordinates of the user when they sign up or log in. The reduced coordinate values are then concatenated, saved in shared preferences on the user's phone, and then set as the primary nodes in the database. This allows searching through the database to be restricted to just the sector the user is currently in which is required by a feature of the app. See the example the nodal layout of the database below:

在此处输入图像描述

The Problem:

This system works great, except for that when the user logs in on a new device (or if the shared preferences are lost) from outside the original sector, or from the previous sector, there is no way to know the previous or original sector value.

The Answer:

The answer I came up with is to search every single sector node in the database for the unique uid easily acquired by the following code:

FirebaseAuth mAuth = FirebaseAuth.getInstance()
String currentUser = mAuth.getCurrentUser().getUid();

However, I don't know how to search through every single node (of which there may be thousands because there are thousands of potential sectors) in the database for a particular child . Note that every primary node has a different name, but they all contain the child "users" which can then hold any number of child "uids."

Once the current uid is found in the previous sector-node, my intent is to transfer all of the children of the current uid in the previous sector to the new one. I want to avoid iterating locally through the entire database for the uid as well.

private DatabaseReference userRef = FirebaseDatabase.getInstance().getReference();

mLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String email = mEmail.getText().toString();
                final String password = mPassword.getText().toString();
                final String currentUserId = mAuth.getUid();
                mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(LoginActivity.this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (!task.isSuccessful()) {
                            Toast.makeText(LoginActivity.this, "sign in error", Toast.LENGTH_SHORT);
                        } else {
                            if (task.isSuccessful()){
                                userRef.addValueEventListener(new ValueEventListener() {
                                    @Override
                                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                                    }

                                    @Override
                                    public void onCancelled(@NonNull DatabaseError databaseError) {

                                    }
                                })
                            }
                        }
                    }
                });
            }
        });

All this needs to occur after the success of a sign-in event as shown above. I have a feeling I need to use a dataSnapshot for this but I am unsure. I also read another post and considered the following to be the start of something that might work, but I don't know:

Query searchQuery = userRef.child("Users").equalTo(currentUserId); 

The flow of the query should be this: Search first node -> Navigate to Users --> iterate through for currentUid --> If currentUid is not found Search the second node ... and so on and so forth until the currentUid is found.

If anyone has the answer or any suggestions, guidance, or hints, I would be very grateful. Thank you.

A Firebase Database query can only contain one unknown level in the path. Your current structure doesn't allow you to search all sectors for a specific user. You can search across all users in a single section, but not across sectors.

So while your current code makes it easy to find all users in a specific sector, or even range of sectors, it doesn't make it easy to find the sector for a specific user. To allow the latter use-case you'll need to add an additional data structure for that purpose. Typically something like:

"user-locations": {
  "$uid": "
    "sector": "37-123",
    "location": "..."
  }
}

So this means that when a user moves, you'll need to update their location in two places.

This sort of data duplication is common in NoSQL databases, where you need to update your data model to allow the use-cases. It is also quite common to have more complex write operations, in order to make read operations simpler and more scalable.

For more on this, see my answers to:

And:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM