かめ。ブログ

MicroCMSのデータを取得してAlgoliaに登録するNodeの処理

2024年1月14日
2024年1月15日

目次

必要なnpm

package.json

  "scripts": {
    "generateMicroCmsToAlgolia": "node ./src/utils/server/generateMicroCmsToAlgolia",
  },

build時に、合わせて実行するようにしておくと良いです。

.env

MICROCMS_SERVICE_DOMAIN=MicroCMSのドメイン
MICROCMS_API_KEY=MicroCMSのAPIキー
SITE_DOMAIN=サイトのドメイン
NEXT_PUBLIC_ALGOLIA_APPLICATION_ID=AlgoliaアプリケーションID
ALGOLIA_ADMIN_API_KEY=Algolia管理APIキー
NEXT_PUBLIC_ALGOLIA_INDEX=Algoliaインデックス

generateMicroCmsToAlgolia

const axios = require('axios').default;
const removeMd = require('remove-markdown');
const algoliasearch = require('algoliasearch');

const getMicroCMSdata = async (name, limit, query) => {
  const url = `https://${process.env.MICROCMS_SERVICE_DOMAIN}.microcms.io/api/v1/${name}`;
  const apiKeyHeaderOption = {
    headers: { 'X-API-KEY': process.env.MICROCMS_API_KEY },
  };

  const getUrlOption = (number, url) => {
    return url + `?limit=${number}${query || ''}`;
  };

  const getTotalCountUrl = getUrlOption(0, url);
  const totalCountUrlData = await axios
    .get(getTotalCountUrl, apiKeyHeaderOption)
    .then((r) => r.data);
  const { totalCount } = await totalCountUrlData;

  const getContentUrl = getUrlOption(limit || totalCount, url);
  const contentUrlData = await axios
    .get(getContentUrl, apiKeyHeaderOption)
    .then((r) => r.data);
  const data = await contentUrlData;

  return data;
};

const generateMicroCmsToAlgolia = async () => {
  if (
    !process.env.MICROCMS_SERVICE_DOMAIN ||
    !process.env.MICROCMS_API_KEY ||
    !process.env.SITE_DOMAIN ||
    !process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID ||
    !process.env.ALGOLIA_ADMIN_API_KEY ||
    !process.env.NEXT_PUBLIC_ALGOLIA_INDEX
  ) {
    return;
  }
  const { contents: entries } = await getMicroCMSdata(
    'entries',
    999,
    '&orders=-publishedAt&fields=id,title,categories.label,categories.value,tags.label,tags.value,publishedAt,image,description,body'
  );

  const htmlTagRegex = /<("[^"]*"|'[^']*'|[^'">])*>/g;

  const objects = entries.map((entry) => {
    return {
      objectID: entry.id,
      url: `https://${process.env.SITE_DOMAIN}/entry/${entry.id}`,
      title: entry.title,
      description: entry.description,
      tags: entry.tags,
      categories: entry.categories,
      content: entry.body
        .map((v) => {
          const commentValue = v;
          if (v.fieldId === 'comments') {
            return commentValue.comments
              .map((v) => `${v.name ? `${v.name}: ` : ''}${v.text}`)
              .join('');
          }

          if (v.fieldId === 'html') {
            return v.value.replace(htmlTagRegex, '');
          }

          if (v.fieldId === 'markdown') {
            return removeMd(v.value);
          }

          if (v.fieldId === 'richeditor' && v.value) {
            return v.value.replace(htmlTagRegex, '');
          }
        })
        .join('')
        .slice(0, 3200), // 数が多いAlgoliaの無料版の文字制限に引っかかってしまうため制限しています
    };
  });

  const client = algoliasearch(
    process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID,
    process.env.ALGOLIA_ADMIN_API_KEY
  );
  const index = client.initIndex(process.env.NEXT_PUBLIC_ALGOLIA_INDEX);
  await index.saveObjects(objects, { autoGenerateObjectIDIfNotExist: true });
};

generateMicroCmsToAlgolia().catch((error) => {
  console.error(error);
});

これは、このブログのfieldをもとに制作しています。fieldIdentryの項目については それぞれのMicroCMSの設定に合わせてください。

実行方法

MICROCMS_API_KEY=${MICROCMS_API_KEY} MICROCMS_SERVICE_DOMAIN=${MICROCMS_SERVICE_DOMAIN} NEXT_PUBLIC_ALGOLIA_APPLICATIO_IDN=${APPLICATIO_IDN} ALGOLIA_ADMIN_API_KEY=${ALGOLIA_ADMIN_API_KEY} NEXT_PUBLIC_ALGOLIA_INDEX=${ALGOLIA_INDEX} SITE_DOMAIN=${SITE_DOMAIN} npm run generateMicroCmsToAlgolia

NEXT_PUBLICとなっているのは、Nextで使用するものも含まれているため共通で使えるようにしています。



関連する記事