20

As a newbie in firebase I tried to mimic a kind of "where clause" request to retrieve the user's wallet in this simple use case:

User
   48bde8f8-3b66-40bc-b988-566ccc77335c
      email: "toto@acme.com"
      username: "userTest1"

UserWallet
   F4PvtvNT2Z
      coins: 26
      someList
         elemet1
         elemet2 
      user: "48bde8f8-3b66-40bc-b988-566ccc77335c"

First I tried to code my request like this:

Firebase root = new Firebase("https://myApp.firebaseio.com/");
Firebase ref = root.child("UserWallet");
Query query = ref.equalTo("48bde8f8-3b66-40bc-b988-566ccc77335c", "user");

The result was null, So I wrote this query:

Query query = ref.orderByChild("user").equalTo("48bde8f8-3b66-40bc-b988-566ccc77335c", "user");

Result was null again. The only way to retrieve the wallet was with this query:

Query query = ref.orderByChild("user").equalTo("48bde8f8-3b66-40bc-b988-566ccc77335c");

So Should I have to always use en "orderByChild()" query before to use "equalTo()"?
And so, what is the purpose of the query "equalTo(String value, String key)" compare to "equalTo(String value) since only the second one works correctly?

Gene Bo
  • 11,284
  • 8
  • 90
  • 137
ThierryC
  • 1,794
  • 3
  • 19
  • 34

2 Answers2

9

There are some edge cases that don't need an orderBy...(), but in general you'll need an orderBy...() before a filtering operation (equalTo(), startAt(), endAt()).

I highly recommend that you first read the Firebase programming guide for Android (95% of it applies to regular Java too). A few hours spent in that guide, will save dozens of questions here. For example: this is the section on queries.

After reading that, you might also want to read this guide on NoSQL Data Modeling. It covers many common patterns in NoSQL data modeling and will help you realize early on that trying to map SQL queries to a NoSQL database is a logical idea, but seldom a good one.

My initial (without any idea on your use-cases, except for "I need to be able to find the wallets for a user") model:

UserWallet
   "48bde8f8-3b66-40bc-b988-566ccc77335c"
      "F4PvtvNT2Z"
         coins: 26
         someList
            element1
            element2 

In the above model, I've inverted the Wallet and User under UserWallet, so that looking up the wallet(s) for a user becomes easier.

ref.child('UserWallet').child(auth.uid).addValueEventListener(...

Note that there is no query involved here, so loading will be equally fast no matter how many users you have in your database.

Or alternatively:

User
   "48bde8f8-3b66-40bc-b988-566ccc77335c"
      email: "toto@acme.com"
      username: "userTest1"

Wallet
   "F4PvtvNT2Z"
      coins: 26
      someList
         element1
         element2 

UserWallet
   "48bde8f8-3b66-40bc-b988-566ccc77335c"
      "F4PvtvNT2Z"

Now we've complete flattened the structure. To determine the wallets of a user, you go to UserWaller/$uid and then load each wallet from Wallets/$walletid. It may be a bit more code, but it'll be extremely efficient (since there are no queries involved).

Anthony
  • 3,989
  • 2
  • 30
  • 52
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 1
    Thanks for your quick answer. I was looking for a kind of data structure that you wrote (the last one) and I needed some confirmations; so that's great. About the Firebase guide, of course I read it before asking a question here, but the relation between orderBy() and EqualTo() was not enough clear for me. – ThierryC Feb 22 '16 at 14:52
  • If there are 10 wallets for the user with uid=1, I have to perform 11 requests, first to ```UserWallet``` and next 10 additional requests. It is still more efficient than use one request with one query? – JCarlosR Nov 01 '16 at 14:56
  • 1
    http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786 – Frank van Puffelen Nov 01 '16 at 14:57
  • how to get only the email value? is this correct to get filter the emal value?....usersReference.child("users") .orderByChild("email") .startAt(s.toString()).endAt(s+"\uf8ff"));???? pls help – Grace Venkat Jun 08 '17 at 12:06
  • @GraceVenkat if you meant getting the email of a specific user, you could use `ref.child('User').child(auth.uid).getValue()`. Thereby you could use a getter method to get the email value. – Hanu Jun 09 '17 at 04:25
  • hi @Amruta-Pani, thanks for your reply. actually i need to get the user who have the particular email id from the list of users(i.e for filtering purpose). for that i have used this code "usersReference.child("users") .orderByChild("email") .startAt(s.toString()).endAt(s+"\uf8ff"));"Please see my post here https://stackoverflow.com/posts/44216946/revisions – Grace Venkat Jun 12 '17 at 13:23
0

You can use nested Query for this.! if you have multiple random id you can easily compare them.! DatabaseReference reference = FirebaseDatabase.getInstance().getReference();

    Query query = reference.child("user");
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                // dataSnapshot is the "issue" node with all children with id 0
                for (DataSnapshot issue : dataSnapshot.getChildren()) {
                    // do something with the individual "issues"

Query query = reference.child("user").child(dataSnapshot.getKey().equals(YourData)));
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {






                }

            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
Atif AbbAsi
  • 5,633
  • 7
  • 26
  • 47