Skip to content

Instantly share code, notes, and snippets.

@cliffhall
Last active November 29, 2018 11:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cliffhall/cac5b5e65d98981a0ea10586ad230d31 to your computer and use it in GitHub Desktop.
Save cliffhall/cac5b5e65d98981a0ea10586ad230d31 to your computer and use it in GitHub Desktop.
Using Firebase Cloud Functions to Manage a Compound Key Index
/**
* Function: indexArtist
*
* Triggered by writes to: /artists/:id
* Responds by writing to: /indexes/artist_by_genre (once for each Genre the Artist has chosen)
*
* If there was a previous value, all associated index entries are removed first.
* So, if the artist display name has changed or the genre list has changed,
* the index will be properly synchronized.
*
* See the explanatory article here:
* http://cliffordhall.com/2017/04/using-firebase-cloud-functions-manage-compound-key-index/
*
* @type {CloudFunction<any>|CloudFunction<DeltaSnapshot>}
*/
exports.indexArtist = functions.database.ref('/artists/{uid}')
.onWrite(event => {
// All the write promises this function will create
let writes = [];
let artistByGenreIndex = admin.database().ref('/indexes/artist_by_genre');
console.log('Triggered by artist', event.params.uid, event.data.val().user.name.display);
// Remove any previous entries since genre or display name may have changed
var previous = event.data.previous.exists() ? event.data.previous.val() : null;
let deletes = [], key, val;
if (previous && previous.genres){
console.log('Removing old index entries...');
previous.genres.forEach( genre => {
key = genre.name + previous.user.name.display;
deletes.push( artistByGenreIndex.child(key).set(null) );
});
console.log(deletes.length+' entries removed.');
}
// If any previous entries were deleted, wait until they finish
Promise.all(deletes).then(addKeys).catch(addKeys);
// You must return a Promise when performing async tasks in a Firebase Cloud Function
return Promise.all(writes);
// Add the keys for all Genres this Artist has chosen
function addKeys() {
const current = event.data.exists() ? event.data.val() : null;
if (current && current.genres) {
console.log('Indexing artist: ', event.params.uid, current.user.name.display);
current.genres.forEach( genre => {
key = genre.name + current.user.name.display;
val = {key: key, artist: {user: current.user}, genre:genre};
writes.push( artistByGenreIndex.child(key).set(val) );
});
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment