Populate

Populate allows you to replace IDs within your data with other data from Firebase. This is very useful when trying to keep your data flat. Some would call it a join, but it was modeled after the mongo populate method.

Initial data from populate is placed into redux in a normalized pattern following defined redux practice of normalizing. populatedDataToJS helper used in the connect function then builds populated data out of normalized data within redux (NOTE: This does not apply if you are using v1.1.5 or earlier).

A basic implementation can look like so:

const populates = [
  { child: 'owner', root: 'users' } // replace owner with user object
]

@firebaseConnect([
  // passing populates parameter also creates all necessary child queries
  { path: 'todos', populates }
])
@connect(({ firebase }) => ({
  // populate original from data within separate paths redux
  todos: populatedDataToJS(firebase, 'todos', populates),
  // dataToJS(firebase, 'todos') for unpopulated todos
}))

Some Things To Note

  • Population happens in two parts:
    1. firebaseConnect - based on populate settings, queries are created for associated keys to be replaced. Query results are stored in redux under the value of root in the populate settings.
    2. connect - Combine original data at path with all populate data (in redux from queries created by passing populate settings to firebaseConnect)
  • Populate creates a query for each key that is being replaced
  • Results of populate queries are placed under their root

Examples

List of todo items where todo item can contain an owner parameter which is a user's UID like so:

{ "text": "Some Todo Item", "owner": "Iq5b0qK2NtgggT6U3bU6iZRGyma2" }
Example Data
"todos": {
  "ASDF123": {
    "text": "Some Todo Item",
    "owner": "Iq5b0qK2NtgggT6U3bU6iZRGyma2"
   }
 },
 "displayNames": {
   "Iq5b0qK2NtgggT6U3bU6iZRGyma2": "Morty Smith",
   "6Ra53mf3U9Qmdwah6rXBMgY8smu1": "Rick Sanchez"
 }
 "users": {
   "Iq5b0qK2NtgggT6U3bU6iZRGyma2": {
     "displayName": "Morty Smith",
     "email": "mortysmith@gmail.com"
   },
   "6Ra53mf3U9Qmdwah6rXBMgY8smu1": {
     "displayName": "Rick Sanchez",
     "email": "rick@email.com"
   }
 }

String, Number, or Boolean

When trying to replace the owner parameter with a string such as a displayName from a /displayNames root follow the pattern of #populate=paramToPopulate:populateRoot.

Example Query
const populates = [
  { child: 'owner', root: 'displayNames' }
]
@firebaseConnect([
  { path: '/todos', populates }
  // '/todos#populate=owner:displayNames', // equivalent string notation
])
@connect(
  ({ firebase }) => ({
    todos: populatedDataToJS(firebase, 'todos', populates),
  })
)
Result
ASDF123: {
  text: 'Some Todo Item',
  owner: 'Morty Smith'
 }

Object

Population can also be used to populate a parameter with an object. An example of this would be populating the owner parameter, which is an ID, with the matching key from the users list.

Example Query
const populates = [
  { child: 'owner', root: 'users' }
]
@firebaseConnect([
  { path: '/todos', populates }
  // '/todos#populate=owner:users' // equivalent string notation
])
@connect(
  ({ firebase }) => ({
    todos: populatedDataToJS(firebase, 'todos', populates),
  })
)
Example Result
ASDF123: {
  text: 'Some Todo Item',
  owner: {
    displayName: 'Morty Smith',
    email: 'mortysmith@gmail.com'
  }
}

Object's Parameter

There is also the option to load a parameter from within a population object. An example of this could be populating the owner parameter with the displayName property of the user with a matching ID:

Example
const populates = [
  { child: 'owner', root: 'users', childParam: 'email' }
]
@firebaseConnect([
 { path: '/todos', populates }
 // '/todos#populate=owner:users:email' // equivalent string notation
])
@connect(({ firebase }) => ({
  todos: populatedDataToJS(firebase, 'todos', populates),
}))
Example Result
ASDF123: {
  text: 'Some Todo Item',
  owner: 'mortysmith@gmail.com'
}

Profile Parameters

To Populate parameters within profile/user object, include the profileParamsToPopulate parameter when calling reactReduxFirebase in your compose function.

Parameter

Example Config

Populating username with username from usernames ref.

const config = {
  userProfile: 'users',
  profileParamsToPopulate: [ 'username:usernames' ]
}
Initial Data
{
  users: {
    $uid: {
      email: 'test@test.com',
      displayName: 'Iq5b0qK2NtgggT6U3bU6iZRGyma2'
    }
  }
}
Example Result
{
  users: {
    $uid: {
      email: 'test@test.com',
      displayName: 'someuser'
    }
  }
}

List of Items

Example Config
const config = {
  userProfile: 'users',
  profileParamsToPopulate: [ 'todos:todos' ] // populate list of todos from todos ref
}
Initial Data
{
  users: {
    $uid: {
      email: 'test@test.com',
      todos: {
        0: "ASDF123"
      }
    }
  }
}
Example Result
{
  users: {
    $uid: {
      email: 'test@test.com',
      todos: {
        ASDF123: {
          text: 'Some Todo Item',
          owner: "Iq5b0qK2NtgggT6U3bU6iZRGyma2"
        }
      }
    }
  },
  todos: {
    ASDF123: {
      text: 'Some Todo Item',
      owner: "Iq5b0qK2NtgggT6U3bU6iZRGyma2"
    }
  }
}

results matching ""

    No results matching ""