Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: year aggregation cloud function #101

Merged
merged 9 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading