LoginSignup
0
0

【Strapi】バックエンドをカスタマイズしてUnique Fieldの値でエントリを取得する方法

Posted at

はじめに

Strapiは新規にエントリを作成すると、連番のIDが自動で付与されます。
REST APIではこのIDを使って特定のエントリを取得できますが、連番のIDではなく、一意のフィールドを使って検索をしたいような場面がありました。

今回はバックエンドをカスタマイズして、Unique Filedの値でエントリを取得する方法を紹介します。

なお、Strapiに関しては過去に軽く解説をした記事を投稿したので、こちらを参照してください。

環境

  • TypeScript
  • Strapi: 4.19.1

この記事を読むとできるようになること

  • バックエンドをカスタマイズできる
  • Unique Fieldの値でエントリを取得できる

Unique Fieldの値で検索したい例

今回は、YYYY年MM月DD日の日記を検索したい、という例をモデルにします。
以下は日記Collection Typeのサンプルです。

フィールド 属性
date date, required, unique
body text
以下略

以下のような検索結果になることを目指します。

$ curl <baseUrl>/api/diaries/YYYY-MM-DD \
 -H "Authorization:Bearer <token>
 
 {"data":{"id":1,"attributes":{"date":"2024-01-01","body":"今日はいい天気でした","createdAt":"2024-02-09T01:04:08.931Z","updatedAt":"2024-02-09T01:04:08.931Z"}},"meta":{}}

デフォルトのREST APIを使う場合

デフォルトのREST APIを使う場合はどのような結果が得られるのか確認してみましょう。

Get entries

Get entriesはクエリフィルタに一致するエントリの一覧を返します。
こちらを使う場合はクエリパラメータにfilters[field][operator]=valueと指定することで特定の日付を検索できます。ただし配列形式で取得されてしまうことに注意しましょう。

$ curl "<baseUrl>/api/diaries?filters\[date\]\[$eq\]=2024-01-01" \
 -H Authorization: Bearer <token>
 
{"data":[{"id":1,"attributes":{"date":"2024-01-01","body":"今日はいい天気でした","createdAt":"2024-02-09T01:04:08.931Z","updatedAt":"2024-02-09T01:04:08.931Z"}}],"meta":{"pagination":{"page":1,"pageSize":25,"pageCount":1,"total":1}}}

Get entriesの詳細については、こちらを確認してください。
クエリパラメータについても同様にリンク先で確認できます。

Get an entry

Get an entryはidを元にエントリを検索します。
今回の場合、idは自動で付与される連番になっているため日付で検索するとエラーが返ります。

$ curl <baseUrl>/api/diaries/2024-01-01 \
 -H Authorization: Bearer <token>
 
{"data":null,"error":{"status":404,"name":"NotFoundError","message":"Not Found","details":{}}}

Get an entryのレスポンス例についてはこちらから確認してください。

バックエンドをカスタマイズする

デフォルトの挙動では日付検索が不可能だと確認できたため、Strapiのバックエンドをカスタマイズしていきたいと思います。

Strapi v4のドキュメントには丁度、Back-end customizationという章が用意されています。

上記ページに掲載されている図と照らし合わせると、今回の場合はコントローラーを編集すれば日付で検索できるようになりそうです。

Unique Fieldの値で検索する

早速、コントローラーを編集して日付で検索できるようにしてみましょう。

編集対象のファイルは./src/api/[api-name]/controllers/にあります。今回の場合は./src/api/diary/controllers/diary.tsです。
JavaScriptの場合はモジュール部分など適宜書き変えてください。

./src/api/diary/controllers/diary.ts
/**
 * diary controller
 */

import { factories } from '@strapi/strapi'

export default factories.createCoreController('api::diary.diary', ({ strapi}) => ({
    async findOne(ctx) {
        await this.validateQuery(ctx);
        const sanitizedQueryParams = await this.sanitizeQuery(ctx);

        const entry = await strapi.db.query('api::diary.diary').findOne({
            where: {
                date: ctx.params.id
            },
            select: sanitizedQueryParams.fields
        });

        if (!entry) {
            return ctx.notFound();
        }

        const sanitized = await this.sanitizeOutput(entry, ctx);
        return this.transformResponse(sanitized);
    }
}));

サニタイズとバリデーション

処理の最初とレスポンス前でサニタイズとバリデーションを行っています。
以下の部分です。

await this.validateQuery(ctx);
const sanitizedQueryParams = await this.sanitizeQuery(ctx);

// ...

const sanitized = await this.sanitizeOutput(entry, ctx);

これらは各種設定に基づいてデータのサニタイズを行っています。
関数の概要など詳細については、こちらから確認できます。

Query Engine API

実際の検索はQuery Engine APIを使っています。
コードでは以下の部分です。

const entry = await strapi.db.query('api::diary.diary').findOne({
    where: {
        date: ctx.params.id
    },
    select: sanitizedQueryParams.fields
});

Query Engine APIはStrapiが提供しているAPIの一つで、より低いレベルでデータベース・レイヤーと対話できます。

現時点(2024年2月現在)では、Unique Field検索はこのQuery Engine APIを使うほかないようです。
しかしほとんどのケースでは、Entity Service APIが推奨されています。

👉 In most use cases, it's recommended to use the Entity Service API instead of the Query Engine API.

https://docs.strapi.io/dev-docs/api/query-engine

最終確認

編集後、Get an entryのエンドポイントをもう一度叩いてみます。

$ curl <baseUrl>/api/diaries/2024-01-01 \
 -H Authorization: Bearer <token>

{"data":{"id":1,"attributes":{"date":"2024-01-01","body":"今日はいい天気でした","createdAt":"2024-02-09T01:04:08.931Z","updatedAt":"2024-02-09T01:04:08.931Z"}},"meta":{}}

無事、期待通りの検索結果を受け取ることができました。

まとめ

今回はStrapiのバックエンドをカスタマイズして、Unique Fieldの値でエントリを取得する方法を紹介しました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0