Skip to content

Commit

Permalink
Merge pull request #101 from brown-ccv/firebase-count-function
Browse files Browse the repository at this point in the history
feat: year aggregation cloud function
  • Loading branch information
gtdang authored Jan 15, 2025
2 parents 1cb857d + 4c16a0e commit b742613
Show file tree
Hide file tree
Showing 7 changed files with 5,694 additions and 1 deletion.
16 changes: 15 additions & 1 deletion firebase.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,19 @@
"destination": "/index.html"
}
]
}
},
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
"*.local"
],
"predeploy": "npm --prefix ./functions run test"
}
]
}
2 changes: 2 additions & 0 deletions functions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
*.local
15 changes: 15 additions & 0 deletions functions/aggregator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
exports.calculateYearCounts = (publications) => {
const yearCounts = {};

publications.forEach((publication) => {
const year = publication.year;
if (year) {
yearCounts[year] = (yearCounts[year] || 0) + 1;
}
});

return Object.entries(yearCounts).map(([label, count]) => ({
label,
count,
}));
};
45 changes: 45 additions & 0 deletions functions/functions.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { calculateYearCounts } = require('./aggregator');

describe('calculateYearCounts', () => {
test('correctly aggregates counts by year', () => {
const testData = [
{ year: 2021, title: 'Paper 1' },
{ year: 2021, title: 'Paper 2' },
{ year: 2022, title: 'Paper 3' },
{ year: 2023, title: 'Paper 4' },
{ year: 2024, title: 'Paper 5' },
{ year: 2024, title: 'Paper 6' },
];

const result = calculateYearCounts(testData);

expect(result).toEqual([
{ label: '2021', count: 2 },
{ label: '2022', count: 1 },
{ label: '2023', count: 1 },
{ label: '2024', count: 2 },
]);
});

test('handles empty input', () => {
const result = calculateYearCounts([]);
expect(result).toEqual([]);
});

test('handles missing year data', () => {
const testData = [
{ year: 2021, title: 'Paper 1' },
{ title: 'Paper 2' },
{ year: 2021, title: 'Paper 3' },
{ year: null, title: 'Paper 4' },
{ year: 2023, title: 'Paper 5' },
];

const result = calculateYearCounts(testData);

expect(result).toEqual([
{ label: '2021', count: 2 },
{ label: '2023', count: 1 },
]);
});
});
42 changes: 42 additions & 0 deletions functions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { onDocumentWritten } = require('firebase-functions/v2/firestore');
const { initializeApp } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
const { calculateYearCounts } = require('./aggregator');

// Initialize Firebase Admin SDK
initializeApp();
const db = getFirestore();

// Calculate and save aggregations
async function calculateAggregatedCounts() {
const publicationsSnapshot = await db.collection('publications').get();
const publications = publicationsSnapshot.docs.map(doc => doc.data());

// Count of docs by year
const aggregatedCounts = calculateYearCounts(publications);

// Save the aggregation(s)
await db.collection('aggregations').doc('publicationCounts').set({
counts: aggregatedCounts,
});
}

// onDocumentWritten triggers on create, update, or delete
exports.aggregatePublicationsOnWrite = onDocumentWritten(
'publications/{docId}',
async (event) => {
try {
// log before and after data
const beforeData = event.data.before.data();
const afterData = event.data.after.data();

console.log(`Document written: ${event.params.docId}`);
console.log('Before data:', beforeData);
console.log('After data:', afterData);

await calculateAggregatedCounts();
} catch (error) {
console.error('Error recalculating counts on document write:', error);
}
}
);
Loading

0 comments on commit b742613

Please sign in to comment.