Last active
February 14, 2021 01:30
-
-
Save mcky/d931ab1488a95742b056b466bfeed1ff to your computer and use it in GitHub Desktop.
Sanity.io + Serverless + Algolia
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const algoliasearch = require('algoliasearch'); | |
const request = require('request'); | |
const ndjson = require('ndjson'); | |
const {bindNodeCallback} = require('rxjs'); | |
const {streamToRx} = require('rxjs-stream'); | |
const {bufferCount, map, mergeMap, toArray, tap} = require('rxjs/operators'); | |
// Algolia configuration | |
const algoliaApp = process.env.ALGOLIA_APP_ID; | |
const algoliaIndex = process.env.ALGOLIA_INDEX; | |
// Sanity configuration | |
const projectId = process.env.SANITY_PROJECT_ID; | |
const dataset = process.env.SANITY_DATASET; | |
const sanityExportURL = `https://${projectId}.api.sanity.io/v1/data/export/${dataset}`; | |
module.exports.indexContent = function indexContent(event, context, cb) { | |
// Initiate an Algolia client | |
const client = algoliasearch(algoliaApp, process.env.ALGOLIA_TOKEN); | |
// Initiate the Algolia index | |
const index = client.initIndex(algoliaIndex); | |
// bind the update function to use it as an observable | |
const partialUpdateObjects = bindNodeCallback((...args) => index.saveObjects(...args)); | |
streamToRx( | |
request(sanityExportURL).pipe(ndjson()) | |
).pipe( | |
/* | |
* Pick and prepare fields you want to index, | |
* here we reduce structured text to plain text | |
*/ | |
map(function sanityToAlgolia(doc) { | |
return { | |
objectID: doc._id, | |
body: blocksToText(doc.body || []), | |
blurb: blocksToText(doc.blurb || []), | |
title: doc.title, | |
name: doc.name, | |
slug: doc.slug, | |
}; | |
}), | |
// buffer batches in chunks of 100 | |
bufferCount(100), | |
// 👇uncomment to console.log objects for debugging | |
// tap(console.log), | |
// submit actions, one batch at a time | |
mergeMap(docs => partialUpdateObjects(docs), 1), | |
// collect all batches and emit when the stream is complete | |
toArray() | |
) | |
.subscribe(batchResults => { | |
const totalLength = batchResults.reduce((count, batchResult) => count + batchResult.objectIDs.length, 0); | |
cb(null, `Updated ${totalLength} documents in ${batchResults.length} batches`); | |
}, cb); | |
}; | |
const defaults = {nonTextBehavior: 'remove'}; | |
function blocksToText(blocks, opts = {}) { | |
const options = Object.assign({}, defaults, opts) | |
return blocks | |
.map(block => { | |
if (block._type !== 'block' || !block.children) { | |
return options.nonTextBehavior === 'remove' ? '' : `[${block._type} block]`; | |
} | |
return block.children.map(child => child.text).join(''); | |
}) | |
.join('\n\n'); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
service: algolia-sync | |
provider: | |
name: aws | |
runtime: nodejs8.10 | |
plugins: | |
- serverless-offline | |
- serverless-offline-scheduler | |
functions: | |
indexContent: | |
handler: handler.indexContent | |
events: | |
- schedule: rate(1 day) | |
environment: | |
ALGOLIA_APP_ID: 'your_app_id_here' | |
ALGOLIA_TOKEN: 'your_token_here' | |
ALGOLIA_INDEX: 'your_index_name_here' | |
SANITY_PROJECT_ID: 'your_sanity_project_id_here' | |
SANITY_DATASET: 'your_sanity_dataset_here' | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment