Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to query related records in Firebase?

Tags:

firebase

Given this database structure in Firebase:

{
    "users": {
        "user1": {
            "items": {
                "id1": true
            }
        },
        "user2": {
            "items": {
                "id2": true
            }
        }
    },

    "items": {
        "id1": {
            "name": "foo1",
            "user": "user1"
        },
        "id2": {
            "name": "foo2",
            "user": "user2"
        }
    }
}

which is a more efficient way of querying the items belonged to a specific user?

The Firebase docs seem to suggest this:

var itemsRef = new Firebase("https://firebaseio.com/items");
var usersItemsRef = new Firebase("https://firebaseio/users/" + user.uid + "/items");
usersItemsRef.on("child_added", function(data){
    itemsRef.child(data.key()).once("value", function(itemData){
        //got the item
    });
});

but using the .equalTo() query works as well:

var ref = new Firebase("https://firebaseio.com/items");
ref.orderByChild("user").equalTo(user.uid).on("child_added", function(data){
    //got the item
});

The latter code seems more concise and doesn't require denormalization of the item keys into the user records but it's unclear to me if it's a less efficient methodology (assuming I create an index on "user").

thanks.

like image 628
mitchgrasso Avatar asked Nov 26 '14 15:11

mitchgrasso


1 Answers

This is rather old one, but when working on the firebase-backed app, I found myself dealing with similar issues quite often.

.equalTo is more time-efficient (especially, if one user owns big number of items). Although n+1 subscriptions does not lead to n+1 networking roundtrips to the cloud, there is some performance penalty for having so many open subscriptions.

Moreover, .equalTo approach does not lead to denormalization of your data.

There is a gotcha however: When you'll want to secure the data, the .equalTo approach may stop working at all.

To allow user to call orderByChild("user").equalTo(user.uid), they must have read privilege to 'items' collection. This read permission is valid for the whole sub-document rooted at /items.

Summary: If user1 is to be prevented from finding out about items of user2, you must use the BYOI (build your own index) approach. That way you can validate that user only reads items that are put to their index.

Finally, disclaimer :) I use firebase only for a short period of time all I got is a few benchmarks and documentation. If I'm mistaken in any way, please correct me.

like image 167
Tomas Kulich Avatar answered Nov 29 '22 20:11

Tomas Kulich