Nikhil
Nikhil

Reputation: 1186

Firebase retrieve data by key

I have a firebase node as follows -

providers
  -userid1
   --userid : userid1
   --keywords
     ---key1 : true
     ---key2 : true
     ---key3 : true
  -userid2
   --userid : userid2
   --keywords
     ---key1 : true
     ---key4 : true
     ---key5 : true

I want to retrieve all the userids that have "key1" in their keywords child.

I tried the following query

var ref = new Firebase(url+"/providers")
ref.orderByChild("keywords").equalTo("key1").on("value", function(snapshot){
console.log(snapshot.numChildren());
})

Also tried -

var ref = new Firebase(url+"/providers")
ref.orderByKey().equalTo("key1").on("value", function(snapshot){
console.log(snapshot.numChildren());
})

I get no results. What am I missing in the query? How are the above two queries different? Both the queries don't work.

Upvotes: 1

Views: 6492

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598728

Your key1 is a key, while equalTo() is used to check for values.

The trick is to query for records where they key1 key has a value of true:

var ref = new Firebase(url+"/providers")
ref.orderByChild("keywords/key1").equalTo(true).on("value", function(snapshot){
    console.log(snapshot.numChildren());
})

Don't forget to add indexes on keywords/key1, etc. to your rules.json:

"providers": {
  "$uid": {
    ".indexOn": ["keywords/key1", "keywords/key2", "keywords/key3", "keywords/key4", "keywords/key5"]
  }
}

You'll probably find that adding such indexes is unmaintainable, which is a good indication that your data structure should be improved. In this case, that can be done by adding a secondary, inverted index that maps from each specific key back to the matching providers:

providers
  userid1
    userid : userid1
    keywords
      key1 : true
      key2 : true
      key3 : true
  userid2
    userid : userid2
    keywords
      key1 : true
      key4 : true
      key5 : true
providers_by_keyword:
  key1:
    userid1: true
    userid2: true
  key2:
    userid1: true
  key3:
    userid1: true
  key4:
    userid2: true
  key5:
    userid2: true

Now you can execute both operations without a query:

  1. get all keywords for user1: ref.child('users/user1/keywords').on(...
  2. get all users for key1: ref.parent().child('providers_by_keyword/key1').on(...

This approach of creating secondary indexes is known as denormalizing in NoSQL databases. It is described in Firebase's denormalizing is normal blog post. I also recommend reading this article about NoSQL data modeling.

Upvotes: 2

Related Questions