I have an Azure Function app configured with Azure Functions Blob Storage trigger. The goal is to update Azure Cognitive Search index when a file is uploaded to Azure Blob Storage, and to delete the corresponding document from the search index when a file is deleted from Azure Blob Storage. Upload trigger works when upload file to Blob Storage.
Issue: However, I'm facing issues with the delete trigger not firing.
- How can I modify my Azure Function app to ensure that when a file is deleted from Azure Blob Storage, the corresponding document is deleted from Azure Cognitive Search?
- Is there a way to achieve this using Azure Functions and Blob Storage trigger, or do I need to use a different approach?
Any help or guidance on this issue would be greatly appreciated. Thank you!
Code:
const { app } = require('@azure/functions');
const { BlobServiceClient, StorageSharedKeyCredential } = require('@azure/storage-blob');
const { SearchClient, AzureKeyCredential } = require('@azure/search-documents');
const fs = require('fs');
const path = require('path');
const pdf = require('pdf-parse');
// Azure Blob Storage configuration
const accountName = "";
const accountKey = "";
const containerName = '';
// Azure Cognitive Search configuration
const searchServiceName = "";
const indexName = "";
const apiKey = "";
const blobServiceClient = new BlobServiceClient(
`https://${accountName}.blob.core.windows.net`,
new StorageSharedKeyCredential(accountName, accountKey)
);
const containerClient = blobServiceClient.getContainerClient(containerName);
const searchClient = new SearchClient(
`https://${searchServiceName}.search.windows.net/`,
indexName,
new AzureKeyCredential(apiKey)
);
async function indexBlob(blobTrigger) {
try {
const blobClient = containerClient.getBlobClient(blobTrigger.triggerMetadata.name);
const downloadResponse = await blobClient.download();
console.log("downloadResponse",downloadResponse);
const blobName = blobTrigger.triggerMetadata.name;
const encodedName = Buffer.from(blobTrigger.triggerMetadata.name).toString('base64');
const properties = blobTrigger.triggerMetadata.properties;
const pdfBuffer = await streamToBuffer(downloadResponse.readableStreamBody);
const pdfText = await pdf(pdfBuffer);
const blobContent = pdfText.text;
const document = {
id: encodedName,
content: blobContent,
metadata_storage_content_type: properties.contentType || null,
metadata_storage_size: properties.contentLength || null,
metadata_storage_last_modified: properties.lastModified ? new Date(properties.lastModified).toISOString() : null,
metadata_storage_content_md5: properties.contentMD5 ? Buffer.from(properties.contentMD5).toString('base64') : null,
metadata_storage_name: blobName,
metadata_storage_path: blobTrigger.uri,
metadata_storage_file_extension: path.extname(blobName),
metadata_content_type: properties.contentType || null,
metadata_language: null,
metadata_author: null,
metadata_creation_date: properties.creationTime ? new Date(properties.creationTime).toISOString() : null,
};
await searchClient.uploadDocuments([document]);
console.log(`Document "${document.id}" has been indexed`);
} catch (error) {
console.error(`Error indexing document: ${error}`);
}
}
app.storageBlob('process-blob-for-search', {
path: 'content/{name}',
connection: 'AzureWebJobsStorage',
direction: 'in',
dataType: 'binary',
async handler(context, blobTrigger) {
console.log(`Blob "${blobTrigger.triggerMetadata.name}" has been uploaded`);
console.log(blobTrigger);
await indexBlob(blobTrigger);
}
});
async function streamToBuffer(readableStream) {
return new Promise((resolve, reject) => {
const chunks = [];
readableStream.on("data", (data) => {
chunks.push(data instanceof Buffer ? data : Buffer.from(data));
});
readableStream.on("end", () => {
resolve(Buffer.concat(chunks));
});
readableStream.on("error", reject);
});
}
app.storageBlob('delete-blob-from-search', {
path: 'content/{name}',
connection: 'AzureWebJobsStorage',
direction: 'out',
async handler(context, blobTrigger) {
console.log(`Blob "${blobTrigger.triggerMetadata.name}" has been deleted`);
const blobName = blobTrigger.triggerMetadata.name;
const encodedName = Buffer.from(blobName).toString('base64');
try {
await searchClient.deleteDocuments([encodedName]);
console.log(`Document "${encodedName}" has been deleted from the index`);
} catch (error) {
console.error(`Error deleting document from the index: ${error}`);
}
}
});