⬇️

Cloud FunctionsによるAPI結果の取得と保存

2024/06/01に公開

この記事では、Firebase Cloud Functionsを使用して、APIからフィクスチャ(試合)の統計データを取得し、Firestoreに保存する方法を紹介します。以下のコードは、指定された年と月のフィクスチャIDを取得し、それぞれのフィクスチャIDに対して統計データをAPIから取得してFirestoreに保存するものです。

前提条件

  1. Firebaseプロジェクトが設定されていること。
  2. Firestoreが有効化されていること。
  3. RapidAPIのAPIキーが取得されていること。
  4. firebase-adminfirebase-functionsパッケージがインストールされていること。

コードの説明

以下がCloud Functionsのコードです。

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const fetch = require('node-fetch');
admin.initializeApp();

exports.fetchAndSaveFixtureStatistics = functions.https.onRequest(async (req, res) => {
    // リクエストから年と月を取得
    const year = req.query.year;
    const month = req.query.month;

    if (!year || !month) {
        return res.status(400).send('Year and month are required.');
    }

    // Firestoreからすべてのfixtureデータを取得
    const docRef = admin.firestore().collection('matchResults').doc("39");
    const doc = await docRef.get();

    if (!doc.exists) {
        return res.status(404).send('No document found.');
    } else {
        const data = doc.data();
        const fixtureInfos = data["2023_2024"]; // 2023-2024 シーズンのデータを取得

        const selectedYearMonth = `${year}-${month.padStart(2, '0')}`; // YYYY-MM 形式
        const fixtureIds = fixtureInfos.filter(f => f.kickoffTime.startsWith(selectedYearMonth)).map(f => f.id);

        if (fixtureIds.length === 0) {
            return res.status(404).send('No fixtures found for the specified year and month.');
        }

        console.info(fixtureIds);

        for (let fixtureId of fixtureIds) {
            fixtureId = String(fixtureId);
    
            const url = `https://api-football-v1.p.rapidapi.com/v3/fixtures/statistics?fixture=${fixtureId}`;
            const options = {
                method: 'GET',
                headers: {
                    'X-RapidAPI-Key': 'YOUR_RAPIDAPI_KEY',
                    'X-RapidAPI-Host': 'api-football-v1.p.rapidapi.com'
                }
            };
    
            try {
                const response = await fetch(url, options);
                const result = await response.json();
                if (!result.response || result.response.length === 0) {
                    throw new Error('No statistics data found for fixture ID: ' + fixtureId);
                }
    
                const statisticsInfos = result.response.map(teamStat => {
                    if (!teamStat.team || !teamStat.statistics) {
                        throw new Error('Invalid data structure for team statistics');
                    }
    
                    return {
                        teamId: teamStat.team.id,
                        teamName: teamStat.team.name,
                        teamLogo: teamStat.team.logo,
                        statistics: teamStat.statistics.map(stat => ({
                            type: stat.type,
                            value: stat.value !== null ? stat.value : "N/A"  // Handling null values
                        }))
                    };
                });
    
                await admin.firestore().collection('fixtureStatistics').doc(fixtureId).set({ teams: statisticsInfos });
            } catch (error) {
                console.error('Error fetching or processing data for fixture:', fixtureId, error);
                return res.status(500).send('Error processing fixture ID ' + fixtureId + ': ' + error.message);
            }
        }

        res.status(200).send('All fixture statistics fetched and saved successfully!');
    }
});

コードの詳細

firebase-adminの設定と初期化

firebase-adminは、Firebaseプロジェクトとやり取りするための管理SDKです。これにより、Firebase Authentication、Firestore、Realtime Databaseなどのサービスにアクセスできます。以下は、firebase-adminの初期化部分です。

const admin = require('firebase-admin');
admin.initializeApp();

このコードは、デフォルトのアプリケーション認証情報を使用して、Firebase Admin SDKを初期化します。これにより、Firebaseのサービスにアクセスできるようになります。

リクエストから年と月を取得

リクエストのクエリパラメータからyearmonthを取得します。これらが存在しない場合は、400エラーを返します。

const year = req.query.year;
const month = req.query.month;

if (!year || !month) {
    return res.status(400).send('Year and month are required.');
}

Firestoreからデータを取得

matchResultsコレクションのドキュメントを取得します。この例ではドキュメントIDは"39"です。

const docRef = admin.firestore().collection('matchResults').doc("39");
const doc = await docRef.get();

if (!doc.exists) {
    return res.status(404).send('No document found.');
}

フィクスチャIDをフィルタリング

取得したデータから指定された年と月に一致するフィクスチャIDを抽出します。

const data = doc.data();
const fixtureInfos = data["2023_2024"]; // 2023-2024 シーズンのデータを取得

const selectedYearMonth = `${year}-${month.padStart(2, '0')}`; // YYYY-MM 形式
const fixtureIds = fixtureInfos.filter(f => f.kickoffTime.startsWith(selectedYearMonth)).map(f => f.id);

if (fixtureIds.length === 0) {
    return res.status(404).send('No fixtures found for the specified year and month.');
}

統計データの取得と保存

各フィクスチャIDに対してAPIから統計データを取得し、fixtureStatisticsコレクションに保存します。

for (let fixtureId of fixtureIds) {
    fixtureId = String(fixtureId);

    const url = `https://api-football-v1.p.rapidapi.com/v3/fixtures/statistics?fixture=${fixtureId}`;
    const options = {
        method: 'GET',
        headers: {
            'X-RapidAPI-Key': 'YOUR_RAPIDAPI_KEY',
            'X-RapidAPI-Host': 'api-football-v1.p.rapidapi.com'
        }
    };

    try {
        const response = await fetch(url, options);
        const result = await response.json();
        if (!result.response || result.response.length === 0) {
            throw new Error('No statistics data found for fixture ID: ' + fixtureId);
        }

        const statisticsInfos = result.response.map(teamStat => {
            if (!teamStat.team || !teamStat.statistics) {
                throw new Error('Invalid data structure for team statistics');
            }

            return {
                teamId: teamStat.team.id,
                teamName: teamStat.team.name,
                teamLogo: teamStat.team.logo,
                statistics: teamStat.statistics.map(stat => ({
                    type: stat.type,
                    value: stat.value !== null ? stat.value : "N/A"  // Handling null values
                }))
            };
        });

        await admin.firestore().collection('fixtureStatistics').doc(fixtureId).set({ teams: statisticsInfos });
    } catch (error) {
        console.error('Error fetching or processing data for fixture:', fixtureId, error);
        return res.status(500).send('Error processing fixture ID ' + fixtureId + ': ' + error.message);
    }
}

res.status(200).send('All fixture statistics fetched and saved successfully!');

注意点

  • APIキーはセキュアな場所に保管し、環境変数などを使用してコード内で参照することを推奨します。
  • エラーハンドリングを適切に行い、ユーザーに対して適切なエラーメッセージを返すようにします。

このコードを実装することで、指定された年と月のフィクスチャ統計データを効率的に取得し、Firestoreに保存することができます。

Discussion