supporting-blog-content/automatically-updating-your-index-nodejs-azure/azure_index.js (94 lines of code) (raw):
const { Client } = require('@elastic/elasticsearch');
const axios = require('axios');
// Retrieve environment variables
const elasticsearchEndpoint = process.env.ELASTICSEARCH_ENDPOINT;
const elasticsearchApiKey = process.env.ELASTICSEARCH_API_KEY;
const nasaApiKey = process.env.NASA_API_KEY;
// Authenticate to Elasticsearch
const client = new Client({
node: elasticsearchEndpoint,
auth: {
apiKey: elasticsearchApiKey
}
});
// Function to get the last update date from Elasticsearch
async function getLastUpdateDate() {
try {
const response = await client.search({
index: 'nasa-node-js',
body: {
size: 1,
sort: [{ close_approach_date: { order: 'desc' } }],
_source: ['close_approach_date']
}
});
if (response.body && response.body.hits && response.body.hits.hits.length > 0) {
return response.body.hits.hits[0]._source.close_approach_date;
} else {
// Default to one day ago if no records found
const today = new Date();
const lastWeek = new Date(today);
lastWeek.setDate(today.getDate() - 1);
return lastWeek.toISOString().split('T')[0];
}
} catch (error) {
console.error('Error fetching last update date from Elasticsearch:', error);
throw error;
}
}
// Asynchronously fetch data from NASA's NEO (Near Earth Object) Web Service
async function fetchNasaData(startDate) {
// Define the base URL for the NASA API request
const url = "https://api.nasa.gov/neo/rest/v1/feed";
const today = new Date();
// Format dates as YYYY-MM-DD for the API request
const endDate = today.toISOString().split('T')[0];
// Setup the query parameters including the API key and date range
const params = {
api_key: nasaApiKey,
start_date: startDate,
end_date: endDate,
};
try {
// Perform the GET request to the NASA API with query parameters
const response = await axios.get(url, { params });
return response.data;
} catch (error) {
// Log any errors encountered during the request
console.error('Error fetching data from NASA:', error);
return null;
}
}
// Transform the raw data from NASA into a structured format for Elasticsearch
function createStructuredData(response) {
const allObjects = [];
const nearEarthObjects = response.near_earth_objects;
// Iterate over each date's objects to extract and structure necessary information
Object.keys(nearEarthObjects).forEach(date => {
nearEarthObjects[date].forEach(obj => {
const simplifiedObject = {
close_approach_date: date,
name: obj.name,
id: obj.id,
miss_distance_km: obj.close_approach_data.length > 0 ? obj.close_approach_data[0].miss_distance.kilometers : null,
};
allObjects.push(simplifiedObject);
});
});
return allObjects;
}
// Asynchronously index data into Elasticsearch
async function indexDataIntoElasticsearch(data) {
const body = data.flatMap(doc => [{ index: { _index: 'nasa-node-js', _id: doc.id } }, doc]);
// Execute the bulk indexing operation
await client.bulk({ refresh: false, body });
}
// Azure Function entry point
module.exports = async function (context, myTimer) {
try {
// Get the last update date from Elasticsearch
const lastUpdateDate = await getLastUpdateDate();
context.log(`Last update date from Elasticsearch: ${lastUpdateDate}`);
// Fetch data from NASA starting from the last update date
const rawData = await fetchNasaData(lastUpdateDate);
if (rawData) {
// Structure the fetched data
const structuredData = createStructuredData(rawData);
// Print the number of records
context.log(`Number of records being uploaded: ${structuredData.length}`);
if (structuredData.length > 0) {
// Store data in a variable and log it (instead of writing to a file)
const flatFileData = JSON.stringify(structuredData, null, 2);
context.log('Flat file data:', flatFileData);
// Index the structured data into Elasticsearch
await indexDataIntoElasticsearch(structuredData);
context.log('Data indexed successfully.');
} else {
context.log('No data to index.');
}
} else {
context.log('Failed to fetch data from NASA.');
}
} catch (error) {
context.log('Error in run process:', error);
}
};