Overview

In the following article, I introduced building applications using the GakuNin RDM API.

In this article, I introduce how to search files in linked storage using the GakuNin RDM API.

Implementation Example

I implemented the search API as follows. Since directly accessing https://rdm.nii.ac.jp/api/v1/search/file/ from the client caused CORS errors, I implemented it as a Next.js API Route.

import { NextResponse } from "next/server";

import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
import { getServerSession } from "next-auth";

export async function GET(req: Request) {
  const session = await getServerSession(authOptions);

  // Get query parameters from URL
  const url = new URL(req.url);
  const query = url.searchParams.get("filter[fulltext]") || "";
  const offset = parseInt(url.searchParams.get("page[offset]") || "0", 10);
  const size = parseInt(url.searchParams.get("page[limit]") || "20", 10);

  const accessToken = session?.accessToken;

  const apiUrl = "https://rdm.nii.ac.jp/api/v1/search/file/";

  const params = {
    api_version: { vendor: "grdm", version: 2 },
    sort: "created_desc",
    highlight: "title:30,name:30,user:30,text:124,comments.*:124",
    elasticsearch_dsl: {
      query: {
        filtered: {
          query: {
            query_string: {
              default_field: "_all",
              fields: [
                "_all",
                "title^4",
                "description^1.2",
                "job^1",
                "school^1",
                "all_jobs^0.125",
                "all_schools^0.125",
              ],
              query,
              analyze_wildcard: true,
              lenient: true,
            },
          },
        },
      },
      from: offset,
      size,
    },
  };

  const res = await fetch(apiUrl, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
    body: JSON.stringify(params),
  });

  const data = await res.json();

  return NextResponse.json(data);
}

Usage Example

You can try it at the following URL. (Login to GakuNin RDM is required.)

https://rdm-leaf-editor.vercel.app/search/?q=.xml

This enables cross-searching XML files across multiple linked storage systems in participating projects, and opening them in the LEAF Writer editor.

The API is available at:

https://rdm-leaf-editor.vercel.app/api/search/?filter[fulltext]=.xml

The following results are returned.

{
  "results": [
    {
      "id": "67da847416000900109e0454",
      "date_created": "2025-03-19T08:46:44.636107+00:00",
      "date_modified": "2025-03-21T04:04:04.011551+00:00",
      "sort_file_name": "01.xml",
      "sort_node_name": "サブプロジェクト",
      "creator_id": "hj3a6",
      "creator_name": "Satoru Nakamura",
      "modifier_id": "jd8ar",
      "modifier_name": "Jun Ogawa",
      "deep_url": "/wzv9g/files/osfstorage/67da847416000900109e0454/",
      "guid_url": "/b45mp/",
      "tags": [],
      "normalized_tags": [],
      "name": "01.xml",
      "normalized_name": "01.xml",
      "category": "file",
      "node_url": "/wzv9g/",
      "node_title": "サブプロジェクト",
      "parent_id": "ys86g",
      "is_registration": false,
      "is_retracted": false,
      "extra_search_terms": "01 xml",
      "node_contributors": [
        {
          "id": "hj3a6"
        },
        {
          "id": "jd8ar"
        }
      ],
      "node_public": false,
      "comments": {},
      "highlight": {
        "name": [
          "01.<b>xml</b>"
        ]
      },
      "comment": null,
      "folder_name": "NII Storage",
      "parent_url": null,
      "parent_title": null
    }
  ],
  "counts": {
    "file": 1,
    "total": 1
  },
  "aggs": {
    "licenses": {},
    "total": 1
  },
  "tags": [],
  "typeAliases": {
    "project": "Projects",
    "component": "Components",
    "registration": "Registrations",
    "user": "Users",
    "total": "All Results",
    "file": "Files",
    "institution": "Institutions",
    "preprint": "Preprints",
    "group": "Groups",
    "wiki": "Wiki",
    "metadata": "Metadata"
  },
  "time": 1.32
}

Summary

I felt that by using the API provided by GakuNin RDM, various applications can be developed.

I am grateful to everyone involved with GakuNin RDM.