Cody Winton
Cody Winton

Reputation: 2989

Firebase Database Access multiple records

Here's my Firebase Data Structure:

{
  "companies": {
    "-Ke_b8p6OBaz1VCeovAH": {
      "display_name": "First User's Company",
      "users": {
        "ir7jjLPA3fXCVsdc4OzzSiH9RJd2": "admin"
      }
    },
    "-Ke_cmhDaIeGJjFwsDI1": {
      "display_name": "First User's Second Company",
      "users": {
        "ir7jjLPA3fXCVsdc4OzzSiH9RJd2": "admin"
      }
    },
    "-Ke_b9OgwY2IBdj5szmJ": {
      "display_name": "Second User's Company",
      "users": {
        "5XcpmN7DgEWNnmWZucyQiOh4TJt2": "admin"
      }
    }
  },

  "users": {
    "ir7jjLPA3fXCVsdc4OzzSiH9RJd2": {
      "display_name": "First User"
    },
    "5XcpmN7DgEWNnmWZucyQiOh4TJt2": {
      "display_name": "Second User"
    }
  }
}

I'm trying to do a query on this data (via. REST for example):

example.firebase.com/companies.json?orderBy="users/ir7jjLPA3fXCVsdc4OzzSiH9RJd2"

My hope is to return

{
  "-Ke_b8p6OBaz1VCeovAH": {
    "display_name": "First User's Company",
    "users": {
      "ir7jjLPA3fXCVsdc4OzzSiH9RJd2": "admin"
    }
  },
  "-Ke_cmhDaIeGJjFwsDI1": {
    "display_name": "First User's Second Company",
    "users": {
      "ir7jjLPA3fXCVsdc4OzzSiH9RJd2": "admin"
    }
  }
}

Instead, I get

{
  "error": "Index not defined, add \".indexOn\": \"users/ir7jjLPA3fXCVsdc4OzzSiH9RJd2\", for path \"/companies\", to the rules"
}

Here's my Firebase Security Rules

{
  "rules": {
    ".read": true,
    ".write": true,

    // Companies
    "companies": {
      ".indexOn": ["display_name", "users"],
    }
  }
}

It's not feasible to update security rules indexing for every user, so how would I handle this?

Upvotes: 0

Views: 601

Answers (1)

Chad Robinson
Chad Robinson

Reputation: 4623

Firebase does not support "filtering" in the class sense you are accustomed to. With your current data structure, you would either need to:

  1. Query all companies and filter on your target user client-side, or
  2. Restructure your users collection to add an attribute indicating which companies the user was an admin of. You could then obtain the user record in one query, and then in a second, query the records for the companies that user is an admin of.

These options sound horrible, but believe it or not, this was specifically the case Firebase was designed to "be fast" at handling. It makes up for code/query inefficiencies through massive scale, so you need to forget a lot of SQL-specific best practices when working with it, like normalizing data, efficient query/join operations, etc. Despite what seems like extra work, if you actually benchmark the operations (and particularly if you enable options such as persistance/caching) you can equal or exceed SQL-environment performance even with these extra steps. Think of it like RISC vs CISC where RISC is Firebase and CISC is SQL.

Upvotes: 1

Related Questions