> ## Documentation Index
> Fetch the complete documentation index at: https://docs.iru.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Iru Query Language

> Iru Query Language (IQL) は、マッピングされた値を整形するための Iru の式言語です: フィールド、演算子、文字列関数、条件式、null セーフなヘルパー。

アプリケーションがサインオン時に受け取る内容 ([SAML アプリ](/ja/identity/applications/saml-applications)の場合は **Subject (NameID)**、[OIDC アプリ](/ja/identity/applications/oidc-applications)の場合は **subject とクレーム**) をマッピングする際、各値は **IQL 式**です。IQL を使用すると、ユーザーのプロファイルから値を取得し、送信前に値を整形できます。

<Info>
  **IQL** (Iru Query Language) は、**マッピング**用の Iru の式言語で、次のようないくつかの場所で使用されます。

  * アプリケーションがサインオン時に受け取る属性とクレーム。
  * 接続されたソースがディレクトリにマッピングするフィールド ([属性マッピング](/ja/identity/directory/attribute-mapping)を参照)。
  * [Auto Group](/ja/identity/directory/auto-groups) ルールとリストフィルター。

  IQL が使用されるすべての場所で同じ構文が機能します。

  IQL はオープンな式言語標準である [CEL (Common Expression Language)](https://cel.dev) に基づいて構築されているため、CEL で有効な式は IQL でも有効です。
</Info>

入力中、マッピングエディターは利用可能なフィールド、関数、演算子を提案し、結果のライブ**プレビュー**を表示します。式はエディター内と保存時に再度**型チェック**に合格する必要があるため、誤りはサインオンや同期に到達する前に表示されます。

## データの参照

参照するものは、式が実行される場所によって異なります。

* **アプリケーションマッピング**は `user` オブジェクトから始まります。そのフィールドはディレクトリの[プロファイル属性](/ja/identity/directory/schema)です。

  ```
  user.email
  user.username
  user.id
  ```

  デフォルトはこれを反映しています。OIDC アプリの subject のデフォルトは `user.id` で、SAML アプリの Subject のデフォルトは `user.username` です。

* **Directory Sync マッピング**は**ソースのフィールド名**を参照します。有効な IQL 識別子は、接続されたシステムから送られてくるとおりに直接記述します。有効な識別子は ASCII 文字またはアンダースコアで始まり、残りは ASCII 文字、数字、アンダースコアで構成されます。

  ```
  email_work
  first_name
  ```

  それ以外の名前は、正確な名前で `__source` から読み取られます。これには、スペース、記号、単一のフィールド名内のドット、ASCII 以外の文字、IQL キーワードが含まれます。たとえば、`__source["Email - Work"]` です。[IQL で値を変換する](/ja/identity/directory/directory-sync#transform-values-with-iql)を参照してください。

フィールド名は**大文字と小文字が区別されます**。ネストされた値にはドット (`user.profile.team`) でアクセスし、リストやマップには `[...]` でアクセスします (以下で説明)。

## 構成要素

| 形式 | 例 | 説明 |
| - | - | - |
| フィールド / 変数 | `first_name`, `user.email` | 名前による値、または値のフィールド。 |
| メソッド呼び出し | `user.email.upperAscii()` | 値**に対して**呼び出される関数。 |
| インデックス | `parts[0]` | 0 から始まる位置によるリストの要素。 |
| マップキー | `entry["label"]` | 文字列キーの下に格納された値。 |
| グループ化 | `(a + b) * c` | 評価順序を制御するための括弧。 |

## リテラル

```
"hello"                             // string (double quotes)
'hello'                             // string (single quotes)
42                                  // whole number
3.14                                // decimal number
true   false                        // booleans
null                                // null
["a", "b", "c"]                     // list
{"label": "work", "primary": true}  // map (string keys)
```

文字列は、`\n`、`\t`、`\\`、`\"`、`\uXXXX` などの一般的なエスケープをサポートしています。

## 演算子

<Tabs>
  <Tab title="算術">
    | 演算子 | 例 | 機能 |
    | - | - | - |
    | `+` | `first_name + " " + last_name` | 数値を加算するか、**文字列を結合**します。 |
    | `-` `*` `/` | `a * b` | 減算、乗算、除算。 |
    | `%` | `a % b` | 剰余 (モジュロ)。 |
  </Tab>

  <Tab title="比較">
    | 演算子 | 例 | 機能 |
    | - | - | - |
    | `==` `!=` | `user.domain == "acme.com"` | 等しい、等しくない。 |
    | `<` `<=` `>` `>=` | `user.level >= 3` | 順序の比較。 |
  </Tab>

  <Tab title="論理">
    | 演算子 | 例 | 機能 |
    | - | - | - |
    | `&&` | `a && b` | AND。 |
    | <code>\|\|</code> | <code>a \|\| b</code> | OR。 |
    | `!` | `!a` | NOT。 |
  </Tab>

  <Tab title="メンバーシップと選択">
    | 演算子 | 例 | 機能 |
    | - | - | - |
    | `in` | `user.domain in ["acme.com", "acme.io"]` | 値がリストに含まれる場合、またはキーがマップに含まれる場合に true。 |
    | `? :` | `name != "" ? name : "unknown"` | 条件式: いずれかの値を選択します。 |
  </Tab>
</Tabs>

### 優先順位

結合が最も強いものから最も弱いものの順です。迷った場合は括弧を追加してください。

```
1) a.b   a()   a[i]   ()      // member access, calls, indexing, grouping
2) !a    -a                   // unary not, negation
3) *  /  %                    // multiply, divide, remainder
4) +  -                       // add, subtract (and string +)
5) <  <=  >  >=  in           // comparison and membership
6) ==  !=                     // equality
7) &&                         // and
8) ||                         // or
9) ? :                        // conditional
```

## 文字列関数

文字列操作は、`value.method(...)` の形式で値に対する**メソッド**として記述します。

| メソッド | 例 | 機能 |
| - | - | - |
| `upperAscii` / `lowerAscii` | `user.email.lowerAscii()` | 値を大文字または小文字にします。 |
| `trim` | `first_name.trim()` | 前後の空白を削除します。 |
| `split` | `user.email.split("@")` | 区切り文字でリストに分割します。`[n]` でインデックスを指定します。 |
| `replace` | `phone.replace("-", "")` | 部分文字列のすべての出現を別の文字列に置き換えます。 |
| `contains` | `user.email.contains("+")` | 値に部分文字列が含まれる場合に true。 |
| `startsWith` / `endsWith` | `user.email.endsWith("@acme.com")` | 値の先頭または末尾をテストします。 |
| `indexOf` | `username.indexOf(".")` | 部分文字列の位置。存在しない場合は `-1`。 |
| `matches` | `user.email.matches("^[a-z]+@acme\\.com$")` | 値が正規表現に一致する場合に true。 |
| `size` | `user.email.split("@").size()` | 文字列またはリストの長さ。`size(value)` としても使用できます。 |

## 条件式とデフォルト

条件演算子は、値が空である可能性がある場合にフォールバックを指定する最も簡単な方法です。

```
// Use the first name, or fall back to the username when it's empty
user.firstName != "" ? user.firstName : user.username
```

より高度な null 処理のために、IQL には以下の **optional** (null セーフ) ヘルパーもあります。

## オプション値

オプションヘルパーを使用すると、エラーを発生させることなく、**欠落している可能性のある**値を扱うことができます。*optional* は値を保持するか、空です。

<Tabs>
  <Tab title="作成">
    ```
    optional.of(value)            // wrap a value as an optional
    optional.ofNonZeroValue(value) // empty if the value is "zero" (see below)
    optional.none()               // an empty optional
    ```

    `ofNonZeroValue` は次のものを空として扱います: 空の文字列 `""`、`0`、`false`、空のリスト `[]`、空のマップ `{}`、`null`。
  </Tab>

  <Tab title="安全にアクセス">
    ```
    value.?field     // optional field access (yields an optional)
    list[?i]         // optional index (empty instead of an error if out of range)
    ```
  </Tab>

  <Tab title="値の取り出し">
    ```
    opt.hasValue()          // true if the optional holds a value
    opt.value()             // the inner value (errors if empty)
    opt.orValue(fallback)   // the value, or the fallback if empty
    a.or(b)                 // the first of two optionals that has a value
    ```
  </Tab>

  <Tab title="変換">
    ```
    opt.optMap(x, expr)      // transform the inner value if present, else stay empty
    opt.optFlatMap(x, expr)  // like optMap, when expr itself returns an optional
    ```
  </Tab>
</Tabs>

```
// A default when a field is empty
optional.ofNonZeroValue(first_name).orValue("anon")

// Split an email and safely take the domain, falling back to ""
optional.ofNonZeroValue(email_work).optMap(e, e.split("@"))[?1].orValue("")
```

## コメントと空白

空白は意味を持たず、`//` は行末まで続くコメントを開始します。

```
user.firstName + " " + user.lastName   // build a display name
```

## 例

```
// A field, as-is
user.email

// Upper-case the value
user.email.upperAscii()

// Build a display name from two fields
user.firstName + " " + user.lastName

// The local part of an email, before the "@"
user.email.split("@")[0]

// A field from the user's first address
user.addresses[0].city

// Choose a fallback when a field is blank
user.firstName != "" ? user.firstName : user.username

// A structured value, built as a map
{"email": user.email, "primary": true}
```

<Tip>
  公開する前に、マッピングエディターの**プレビュー**を使用して、式が期待どおりの結果を生成することを確認してください。プレビューには、Iru が送信または保存する正確な値が表示されます。
</Tip>

## 次のステップ

<CardGroup cols={2}>
  <Card title="アプリケーションマッピング" icon="arrows-left-right" href="/ja/identity/applications/application-mapping">
    IQL の値を、アプリケーションが受け取るアサーションまたはトークンにマッピングします。
  </Card>

  <Card title="属性マッピング" icon="code" href="/ja/identity/directory/attribute-mapping">
    同じ IQL を使用して、接続されたソースをディレクトリにマッピングします。
  </Card>

  <Card title="自動グループ" icon="wand-magic-sparkles" href="/ja/identity/directory/auto-groups">
    プロファイル属性に対する IQL ルールでグループメンバーシップを駆動します。
  </Card>

  <Card title="プロファイル属性" icon="table-list" href="/ja/identity/directory/schema">
    式が値を取得する `user` フィールド。
  </Card>
</CardGroup>
