1
{
  "SHOPPING_LIST" : {
    "kPLZpp809gePpBiBojsngjZdg6A3:228c1e5b-fe11-4f06-ad32-c54734044a5e" : {
      "listId" : "kPLZpp809gePpBiBojsngjZdg6A3:228c1e5b-fe11-4f06-ad32-c54734044a5e",
      "listName" : "Lista de la compra de Jesús Lunar Pérez",
      "owner" : "kPLZpp809gePpBiBojsngjZdg6A3",
      "pendingListElements" : 0,
      "sharedWithUsers" : [ "kPLZpp809gePpBiBojsngjZdg6A3" ]
    }
  },
  "users" : {
    "kPLZpp809gePpBiBojsngjZdg6A3" : {
      "label" : "Jesús Lunar Pérez",
      "userId" : "kPLZpp809gePpBiBojsngjZdg6A3",
      "userInfo" : {
        "nickName" : "Jesús Lunar Pérez",
        "userEmail" : "lunarjchav@gmail.com"
      }
    }
  }
}

I have stored this data in a realtime-database and I'm trying to get all SHOPPING_LISTs which are shared with some users.

I'm querying data such as:

Query query = FirebaseDatabase.getInstance()
        .getReference("SHOPPING_LIST")
        .orderByChild("sharedWithUsers")
        .equalTo(userId /*userId = "kPLZpp809gePpBiBojsngjZdg6A3"*/)
        ;

but I'm not getting anything.

What am I doing wrong? Is there a way to debug queries?

Thanks in advance.

EDITED:

Finally, as suggested, I changed data organization to:

{
  "SHOPPING_LIST" : {
    "kPLZpp809gePpBiBojsngjZdg6A3:f65836e3-1f79-43a8-aae8-5a9bb9eb3929" : {
      "listId" : "kPLZpp809gePpBiBojsngjZdg6A3:f65836e3-1f79-43a8-aae8-5a9bb9eb3929",
      "listName" : "Lista de la compra de Jesús Lunar Pérez",
      "owner" : "kPLZpp809gePpBiBojsngjZdg6A3",
      "pendingListElements" : 0,
      "sharedWithUsers" : {
        "kPLZpp809gePpBiBojsngjZdg6A3" : true
      }
    }
  },
  "users" : {
    "kPLZpp809gePpBiBojsngjZdg6A3" : {
      "label" : "Jesús Lunar Pérez",
      "userId" : "kPLZpp809gePpBiBojsngjZdg6A3",
      "userInfo" : {
        "nickName" : "Jesús Lunar Pérez",
        "userEmail" : "lunarjchav@gmail.com"
      }
    }
  }
}

and I queried like:

        Query query = FirebaseDatabase.getInstance()
                .getReference(ShoppingList.LIST_TYPE.name())
                .orderByChild("sharedWithUsers/" + uid)
                .equalTo(true)
                ;
Chave
  • 71
  • 1
  • 5
  • Does it work when you do it without the `.equalTo(userId /*userId = "kPLZpp809gePpBiBojsngjZdg6A3"*/)`? – André Kool Apr 04 '18 at 15:16
  • Yes, it does. I've logged the value and it's just the same. Note that ""sharedWithUsers" is a JSON array, not an object. I only found examples of retrieving array data but not lists. – Chave Apr 04 '18 at 15:18

1 Answers1

3

Firebase cannot perform a query across array members, to see if it contains a specific value in any position or to add/remove a record.

Note, that Firebase documentation recommends against using arrays. One of the many reasons Firebase recommends that is that it makes the security rules impossible to write.

As usual with NoSQL databases, I will suggest you an alternative structure like this:

  "SHOPPING_LIST" : {
    "kPLZpp809gePpBiBojsngjZdg6A3:228c1e5b-fe11-4f06-ad32-c54734044a5e" : {
      "listId" : "kPLZpp809gePpBiBojsngjZdg6A3:228c1e5b-fe11-4f06-ad32-c54734044a5e",
      "listName" : "Lista de la compra de Jesús Lunar Pérez",
      "owner" : "kPLZpp809gePpBiBojsngjZdg6A3",
      "pendingListElements" : 0,
      "sharedWithUsers" {
        "kPLZpp809gePpBiBojsngjZdg6A3": true
      }
    }

So instead of using arrays, you can us a map, in which the key is the uid and the value is the boolean true.

You can also take a look, here, for more informations.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • 1
    Thanks a lot. That link is what I needed for solving my problem. I'll try and I'll post the solution which works. – Chave Apr 04 '18 at 15:24
  • Note that the above structure (while definitely better) still won't let you easily query for shopping lists shared with a particular user. To allow that you'd need to add an index for each user, which is hardly ever feasible. To allow looking up the shopping lists shared with a user, you'll want to add an inverse mapping. See my answer here for more on this: https://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value – Frank van Puffelen Apr 04 '18 at 15:27
  • @FrankvanPuffelen And I said I'll recommend this practice, in the first place. How could I forget this?! Storing extra data to allow an inverse lookup, it's always a better option. Thanks again for your comment Frank! – Alex Mamo Apr 04 '18 at 15:56