プリザンターのAPIでデータを取得するときのあれこれ

本記事は [Pleasanter(プリザンター) Advent Calendar 2022](https://qiita.com/advent-calendar/2022/pleasanter) 2日目の記事です。

# はじめに
[OSSのノーコード・ローコード開発ツール「プリザンター」](https://pleasanter.org) のAPIを使って、レコードのデータを取得する際のノウハウについて説明します。

## 認証について
プリザンターのAPIを使用する際、APIキーを使用する方法とログインセッションを使用する方法があります。ブラウザ上のJavaScriptを使用する場合には、ログインセッションを使用することで、APIキーの記述を省略することができます。APIキーを省略した場合、ログイン中のユーザの権限で動作します。

|動作環境|認証方式|権限|
|:----|:----|:----|
|外部システム|APIキー|APIキーのユーザ|
|ブラウザ上のJavaScript|APIキー|APIキーのユーザ|
|ブラウザ上のJavaScript|ログインセッション|ログインユーザ|

## 検索について
プリザンターのAPIで検索を行う場合には、項目の種類と設定に応じて検索方法が異なります。正しく設定しないと目的の検索結果が得られません。ColumnFilterHashには、複数の検索条件を指定することができます。複数の検索条件を指定した場合にはAND条件で検索が行われます。

|項目|検索文字列の指定方法|
|:----|:----|
|タイトル、内容、説明項目|文字をそのまま指定|
|分類項目（選択肢なし）|文字をそのまま指定|
|分類項目（選択肢あり）|JSON配列で検索文字を指定|
|数値項目|JSON配列で数字の範囲を指定|
|日付項目|JSON配列で日付の範囲を指定|
|チェック項目|ture / false を指定|

### タイトル、内容、説明項目
下記の例ではサイトID 2 のタイトル項目を'レコードのタイトル'の文字列で検索しています。JSON配列にする必要はありません。文字列を完全一致で検索するためにColumnFilterSearchTypesにExactMatchを指定しています。部分一致で行う場合にはPartialMatchを指定します。ColumnFilterSearchTypesを指定しない場合には、項目に設定された既定の検索種別で検索されますので、APIを使用する場合には必ず指定することをお勧めします。$p.apiGetはプリザンターに組み込まれたメソッドなので、外部システムからリクエストする場合には適宜httpリクエストを発行するコードを記述してください。

```JavaScript
let searchText = 'レコードのタイトル';
let data = {
    id: 2,
    data: {
        ApiKey: '2fe7d4c9...',
        View: {
            ColumnFilterHash: {
                Title: searchText
            },
            ColumnFilterSearchTypes: {
                Title: 'ExactMatch'
            }
        }
    },
    done: function (ret) {
        console.log(ret.Response.Data);
    }
};
$p.apiGet(data);
```

### 分類項目（選択肢なし）
分類項目の選択肢が無い場合はタイトル、内容、説明項目と同じ記述で検索が可能です。

### 分類項目（選択肢あり）
下記の例ではサイトID 2 の選択肢のある分類項目「ClassA」を'設計'または'開発'を含んだJSON配列で検索しています。文字列を完全一致で検索するためにColumnFilterSearchTypesにExactMatchを指定しています。部分一致で行う場合にはPartialMatchを指定します。

```JavaScript
let searchText = JSON.stringify(['設計','開発']);
let data = {
    id: 2,
    data: {
        ApiKey: '2fe7d4c9...',
        View: {
            ColumnFilterHash: {
                ClassA: searchText
            },
            ColumnFilterSearchTypes: {
                ClassA: 'ExactMatch'
            }
        }
    },
    done: function (ret) {
        console.log(ret.Response.Data);
    }
};
$p.apiGet(data);
```

### 数値項目
下記の例では数値項目「NumA」を500,000～1,000,000の範囲で検索しています。

```JavaScript
let searchText = JSON.stringify(['500000,1000000']);
let data = {
    id: 7,
    data: {
        ApiKey: '2fe7d4c9...',
        View: {
            ColumnFilterHash: {
                NumA: searchText
            }
        }
    },
    done: function (ret) {
        console.log(ret.Response.Data);
    }
};
$p.apiGet(data);
```

### 日付項目
下記の例では日付項目「CompletionTime」を2022/11/1～2022/11/30 23:59:59.999の範囲で検索しています。['2022/11/1,2022/11/30 23:59:59.999'] を ['Today'] ['ThisMonth'] ['ThisYear'] に書き換えると、当日、当月、当年で検索可能です。

```JavaScript
let searchText = JSON.stringify(['2022/11/1,2022/11/30 23:59:59.999']);
let data = {
    id: 7,
    data: {
        ApiKey: '2fe7d4c9...',
        View: {
            ColumnFilterHash: {
                CompletionTime: searchText
            }
        }
    },
    done: function (ret) {
        console.log(ret.Response.Data);
    }
};
$p.apiGet(data);
```

## ページング
APIで取得可能なレコード数の上限はデフォルト200件です。こちらは Api.json の PageSize で変更可能です。ページサイズを超えた数のレコードを取得する場合には、下記のように Offset に PageSize を足しながらループ処理で取得します。

```JavaScript
let offset = 0;
let pageSize = 0;
let totalCount = 0;
do {
    let data = {
        id: 2,
        data: {
            ApiKey: '2fe7d4c9...',
            Offset: offset
        },
        done: function (ret) {
            pageSize = ret.Response.PageSize;
            totalCount = ret.Response.TotalCount;
            console.log(ret.Response.Data);
        }
    };
    await $p.apiGet(data);
    offset += pageSize; // 次のページを取得
}
while (offset < totalCount);
```

みなさん、よいクリスマスをお過ごしください。