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