すべてのプロダクト
Search
ドキュメントセンター

Tair (Redis® OSS-Compatible):Doc

最終更新日:Nov 09, 2025

TairDoc は RedisJSON に似たドキュメントデータ構造です。TairDoc を使用して、作成・読取・更新・削除 (CRUD) 操作を実行できます。

概要

主な特徴

  • JSON 標準を完全にサポートします。

  • JSONPath RFC draft-4 標準と部分的に互換性があります。

    説明

    JSON.GET コマンドのみがこのドラフトバージョンをサポートします。

  • JSONPointer 構文を完全にサポートします。

  • バイナリツリーデータストレージにより、子要素の取得が簡素化されます。

  • JSON フォーマットから XML または YAML フォーマットへの変換。

リリースノート

  1. TairDoc は Tair メモリ最適化インスタンスとともにリリースされました。TairDoc は、完全な JSONPointer 構文と部分的な JSONPath 構文をサポートします (JSON.GET コマンドのみが JSONPath 構文をサポートします)。

  2. 2022 年 5 月 17 日に、JSON.GET コマンドの JSONPath 構文を完全にサポートする TairDoc V1.8.4 がリリースされました。インスタンスのマイナーバージョンを 1.8.4 以降に更新することを推奨します。

    TairDoc V1.8.4 は、ドットワイルドカードセレクター、インデックスセレクター、フィルターセレクターなどの特定のセレクターもサポートします。

前提条件

Tair DRAM ベースのインスタンスが作成されていること。

説明

最新のマイナーバージョンは、より多くの機能と高い安定性を提供します。インスタンスを最新のマイナーバージョンに更新することを推奨します。詳細については、「インスタンスのマイナーバージョンを更新する」をご参照ください。インスタンスがクラスターまたは読み書き分離インスタンスである場合は、インスタンス内のプロキシノードを最新のマイナーバージョンに更新することを推奨します。これにより、すべてのコマンドが期待どおりに実行されることが保証されます。

考慮事項

これらの操作は、Tair インスタンスの TairDoc データに対して実行されます。

コマンドリスト

表 1. TairDoc コマンド

コマンド

構文

説明

JSON.SET

JSON.SET key path json [NX | XX]

TairDoc キーを作成し、キーのパスに JSON 要素を格納します。キーとパスが既に存在する場合、このコマンドはキーのパス内の要素を更新します。

JSON.GET

JSON.GET key path [FORMAT XML | YAML] [ROOTNAME root] [ARRNAME arr]

TairDoc キーのパスから JSON 要素を取得します。

JSON.DEL

JSON.DEL key path

TairDoc キーのパスから JSON 要素を削除します。パスが指定されていない場合、キーが削除されます。キーまたはパスが存在しない場合、このコマンドは無視されます。

JSON.TYPE

JSON.TYPE key path

TairDoc キーのパスにある JSON 要素の型を取得します。指定できる型は、booleanstringnumberarrayobjectrawreferenceconstnull です。

JSON.MERGE

JSON.MERGE key path value

JSON 値を指定されたキーのパスにマージします。このコマンドを使用すると、指定されたパスで新しい値の追加、既存の値の更新、値の削除などの操作を実行できます。

JSON.NUMINCRBY

JSON.NUMINCRBY key path value

TairDoc キーのパスにある JSON 要素の値を増やします。要素と、要素に追加する値は、両方とも同じデータ型の整数または double である必要があります。

JSON.STRAPPEND

JSON.STRAPPEND key path json-string

json-string 値を TairDoc キーのパスにある JSON 要素に追加します。json-string 値と JSON 要素は両方とも文字列型である必要があります。

JSON.STRLEN

JSON.STRLEN key path

TairDoc キーのパスから JSON 要素の文字列長を取得します。JSON 要素は文字列型である必要があります。

JSON.ARRAPPEND

JSON.ARRAPPEND key path json [json ...]

TairDoc キーのパスにある配列の末尾に 1 つ以上の JSON 要素を追加します。

JSON.ARRPOP

JSON.ARRPOP key path [index]

TairDoc キーパスの配列内で指定されたインデックスに一致する要素を削除して返します。

JSON.ARRINSERT

JSON.ARRINSERT key path [index] json [json ...]

TairDoc キーの指定されたインデックスの前のパスにある配列に 1 つ以上の JSON 要素を挿入します。

JSON.ARRLEN

JSON.ARRLEN key path

TairDoc キーのパスにある配列の長さを取得します。

JSON.ARRTRIM

JSON.ARRTRIM key path start stop

TairDoc キーのパスにある配列をトリミングします。このコマンドは、開始値と停止値の範囲内にある配列内の要素を保持します。

DEL

DEL <key> [key ...]

1 つ以上の TairDoc キーを削除します。これはネイティブの Redis コマンドです。

説明

次のリストは、このトピックで使用されるコマンド構文の規則について説明しています。

  • 大文字のキーワード: コマンドキーワードを示します。

  • イタリック体のテキスト: 変数を示します。

  • [options]: 角括弧で囲まれたパラメーターがオプションであることを示します。角括弧で囲まれていないパラメーターは指定する必要があります。

  • A|B: 縦棒 (|) で区切られたパラメーターが相互排他的であることを示します。パラメーターのいずれか 1 つのみを指定できます。

  • ...: この記号の前のパラメーターを繰り返し指定できることを示します。

JSON.SET

カテゴリ

説明

構文

JSON.SET key path json [NX | XX]

時間計算量

O(N)

コマンドの説明

TairDoc キーを作成し、キーのパスに JSON 要素を格納します。キーとパスが既に存在する場合、このコマンドはキーのパス内の要素を更新します。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。ルート要素は . または $ です。

  • json: 追加または更新する JSON 要素。

  • NX: パスが存在しない場合にのみ要素を書き込みます。

  • XX: パスが存在する場合にのみ要素を書き込みます。

戻り値

  • 操作が成功した場合、OK が返されます。

  • XX パラメーターが指定されているがパスが存在しない場合、nil が返されます。

  • NX パラメーターが指定されていてパスが既に存在する場合、nil が返されます。

  • ERR could not find object to add, please check path メッセージが返された場合、指定された path は無効です。

  • それ以外の場合は、エラーメッセージが返されます。

コマンド例:

JSON.SET doc $ '{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }'

応答例:

OK

JSON.GET

カテゴリ

説明

構文

JSON.GET key path [FORMAT XML | YAML] [ROOTNAME root] [ARRNAME arr]

時間計算量

O(N)

コマンドの説明

TairDoc キーのパスから JSON 要素を取得します。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。このコマンドは、柔軟なクエリのために JSONPath と JSON 構文の両方をサポートします。詳細については、「JSONPath」および「JSONPointer」をご参照ください。

  • FORMAT: 返される JSON 要素のフォーマット。有効な値: XML および YAML。

  • ROOTNAME : XML 構文の ROOT 要素のタグ。

  • ARRNAME: XML 構文の ARRAY 要素のタグ。

説明

ROOTNAME および ARRNAME パラメーターは、FORMAT パラメーターが XML に設定されている場合にのみ有効です。

戻り値

  • 操作が成功した場合、JSON 要素が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"foo": "bar", "baz" : 42}' コマンドを実行します。

コマンド例:

JSON.GET doc . FORMAT XML ROOTNAME ROOT ARRNAME ARR

応答例:"<?xml version=\"1.0\" encoding=\"UTF-8\"?><ROOT><foo>bar</foo><baz>42</baz></ROOT>"

"<?xml version=\"1.0\" encoding=\"UTF-8\"?><ROOT><foo>bar</foo><baz>42</baz></ROOT>"

JSON.DEL

カテゴリ

説明

構文

JSON.DEL key path

時間計算量

O(N)

コマンドの説明

TairDoc キーのパスから JSON 要素を削除します。パスが指定されていない場合、キーが削除されます。キーまたはパスが存在しない場合、このコマンドは無視されます。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

戻り値

  • 操作が成功した場合、値 1 が返されます。

  • 操作が失敗した場合、値 0 が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"foo": "bar", "baz" : 42}' コマンドを実行します。

コマンド例:

JSON.DEL doc .foo

応答例:

(integer) 1

JSON.TYPE

カテゴリ

説明

構文

JSON.TYPE key path

時間計算量

O(N)

コマンドの説明

TairDoc キーのパスにある JSON 要素の型を取得します。指定できる型は、booleanstringnumberarrayobjectrawreferenceconstnull です。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

戻り値

  • 操作が成功した場合、要素の型が返されます。

  • 操作が失敗した場合、値 0 が返されます。

  • キーまたはパスが存在しない場合、nil が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"foo": "bar", "baz" : 42}' コマンドを実行します。

コマンド例:

JSON.TYPE doc .foo

応答例:

string

JSON.MERGE

カテゴリ

説明

構文

JSON.MERGE key path value

時間計算量

O(N)

コマンドの説明

JSON 値を指定されたキーのパスにマージします。このコマンドを使用すると、指定されたパスで新しい値の追加、既存の値の更新、値の削除などの操作を実行できます。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。このコマンドは、$.a.b.c$.a['b'] などの部分的な JSONPath 構文をサポートしますが、$..$* などの複雑な式はサポートしません。

  • value: マージする JSON 値。フォーマットは Json Merge Patch RFC7386 と互換性があります。

戻り値

  • 操作が成功した場合、OK が返されます。

  • 指定された値が無効な場合、マージパッチの解析に問題があることを示すエラーが発生します。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc $ '{"f1": {"a":1}, "f2":{"a":2}}' コマンドを実行します。

コマンド例:

JSON.MERGE doc $ '{"f1": null, "f2":{"a":3, "b":4}, "f3":[2,4,6]}'

応答例:

OK

コマンドを実行すると、JSON.GET doc . の結果は次のようになります。

"{\"f2\":{\"a\":3,\"b\":4},\"f3\":[2,4,6]}"

JSON.NUMINCRBY

カテゴリ

説明

構文

JSON.NUMINCRBY key path value

時間計算量

O(N)

コマンドの説明

TairDoc キーのパスにある JSON 要素の値を増やします。要素と、要素に追加する値は、両方とも同じデータ型の整数または double である必要があります。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

  • value: 追加する値。

戻り値

  • 操作が成功した場合、パス内の増加した要素が返されます。

  • キーまたはパスが存在しない場合、エラーが発生します。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"foo": "bar", "baz" : 42}' コマンドを実行します。

コマンド例:

JSON.NUMINCRBY doc .baz 10

応答例:

"52"

JSON.STRAPPEND

カテゴリ

説明

構文

JSON.STRAPPEND key path json-string

時間計算量

O(N)

コマンドの説明

json-string 値を TairDoc キーのパスにある JSON 要素に追加します。json-string 値と JSON 要素は両方とも文字列型である必要があります。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

  • json-string: パス内の値に追加する文字列。

戻り値

  • 操作が成功した場合、パスにある文字列の新しい長さが返されます。

  • キーが存在しない場合、値 -1 が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"foo": "bar", "baz" : 42}' コマンドを実行します。

コマンド例:

JSON.STRAPPEND doc .foo rrrrr

応答例:

(integer) 8

JSON.STRLEN

カテゴリ

説明

構文

JSON.STRLEN key path

時間計算量

O(N)

コマンドの説明

TairDoc キーのパスから JSON 要素の文字列長を取得します。JSON 要素は文字列型である必要があります。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

戻り値

  • 操作が成功した場合、パスにある JSON 要素の文字列長が返されます。

  • キーが存在しない場合、値 -1 が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"foo": "bar", "baz" : 42}' コマンドを実行します。

コマンド例:

JSON.STRLEN doc .foo

応答例:

(integer) 3

JSON.ARRAPPEND

カテゴリ

説明

構文

JSON.ARRAPPEND key path json [json ...]

時間計算量

O(M×N)。M は追加する JSON 要素の数、N は配列内の要素の数を指定します。

コマンドの説明

TairDoc キーのパスにある配列の末尾に 1 つ以上の JSON 要素を追加します。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

  • json: 挿入するデータ。

戻り値

  • 操作が成功した場合、配列内の要素の数が返されます。

  • キーが存在しない場合、値 -1 が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"id": [1,2,3]}' コマンドを実行します。

コマンド例:

JSON.ARRAPPEND doc .id null false true

応答例:

(integer) 6

JSON.ARRPOP

カテゴリ

説明

構文

JSON.ARRPOP key path [index]

時間計算量

O(M×N)。M はキーの子要素、N は配列内の要素の数を指定します。

コマンドの説明

TairDoc キーパスの配列内で指定されたインデックスに一致する要素を削除して返します。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

  • index: 配列のインデックス。インデックスは 0 から始まります。負の数は逆のインデックスを示します。このパラメーターが指定されていない場合、デフォルト値は最後の要素です。

戻り値

  • 操作が成功した場合、要素は削除されて返されます。

  • 配列が空の場合、「ERR array index outflow」メッセージが返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"id": [1,2,3]}' コマンドを実行します。

コマンド例:

JSON.ARRPOP doc .id 0

応答例:

"1"

JSON.ARRINSERT

カテゴリ

説明

構文

JSON.ARRINSERT key path [index] json [json ...]

時間計算量

O(M×N)。M は挿入する JSON 要素の数、N は配列内の要素の数を指定します。

コマンドの説明

TairDoc キーの指定されたインデックスの前のパスにある配列に 1 つ以上の JSON 要素を挿入します。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

  • index: 配列のインデックス。インデックスは 0 から始まります。負の数は逆のインデックスを示します。このパラメーターが指定されていない場合、デフォルト値は最後の要素です。

  • json: 挿入するデータ。

戻り値

  • 操作が成功した場合、配列内の要素の数が返されます。

  • 配列が空の場合、「ERR array index outflow」メッセージが返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"id": [1,2,3]}' コマンドを実行します。

コマンド例:

JSON.ARRINSERT doc .id 0 10 15

応答例:

(integer) 5

JSON.ARRLEN

カテゴリ

説明

構文

JSON.ARRLEN key path

時間計算量

O(N)

コマンドの説明

TairDoc キーのパスにある配列の長さを取得します。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

戻り値

  • 操作が成功した場合、配列の長さが返されます。

  • キーが存在しない場合、値 -1 が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"id": [1,2,3]}' コマンドを実行します。

コマンド例:

JSON.ARRLEN doc .id

応答例:

(integer) 3

JSON.ARRTRIM

カテゴリ

説明

構文

JSON.ARRTRIM key path start stop

時間計算量

O(N)

コマンドの説明

TairDoc キーのパスにある配列をトリミングします。このコマンドは、開始値と停止値の範囲内にある配列内の要素を保持します。

オプション

  • key: コマンドが実行される TairDoc オブジェクトを指定する TairDoc キー。

  • path: キーのパス。

  • start: トリミングの開始位置。値は 0 から始まるインデックスです。この位置の要素は、トリミングされた配列に含まれます。

  • stop: トリミングの終了位置。値は 0 から始まるインデックスです。この位置の要素は、トリミングされた配列に含まれます。

戻り値

  • 操作が成功した場合、トリミング後の配列の長さが返されます。

  • キーが存在しない場合、値 -1 が返されます。

  • それ以外の場合は、エラーメッセージが返されます。

事前に JSON.SET doc . '{"id": [1,2,3,4,5,6]}' コマンドを実行します。

コマンド例:

JSON.ARRTRIM doc .id 3 4

応答例:

(integer) 2

JSONPath

TairDoc は、次の互換性のある JSONPath 構文をサポートします。

JSONPath

説明

$

ルート要素。

@

現在の要素。

.name

子要素。

..

要件を満たす位置にある要素。

*

すべての子要素または配列要素を表すことができるワイルドカード。

[ ]

配列のインデックス。0 から始まります。例: [0]。この要素はリストと要素名をサポートします。例: [0,1] および ['name']。

[start:end:step]

配列スライスセレクター。要素は、start から end まで step の増分で取得されます。たとえば、[0:3:1] は、0 番目の要素から 3 番目の要素までが選択されることを示します。増分が -1 の場合 (例: [3:0:-1])、要素は 3 番目の要素から 0 番目の要素まで選択されます。

?...

フィルターセレクター。

()

式をサポートします。優先順位は ( ) > && > || です。詳細については、「JSONPath」をご参照ください。

クエリの例

  1. JSON ドキュメントを作成します。

    コマンド例:

    JSON.SET dockey $
    '{
        "store": {
            "book": [{
                    "category": "reference",
                    "author": "Nigel Rees",
                    "title": "Sayings of the Century",
                    "price": 8.95
                },
                {
                    "category": "fiction",
                    "author": "Evelyn Waugh",
                    "title": "Sword of Honour",
                    "price": 12.99
                },
                {
                    "category": "fiction",
                    "author": "Herman Melville",
                    "title": "Moby Dick",
                    "isbn": "0-553-21311-3",
                    "price": 8.99
                },
                {
                    "category": "fiction",
                    "author": "J. R. R. Tolkien",
                    "title": "The Lord of the Rings",
                    "isbn": "0-395-19395-8",
                    "price": 22.99
                }
            ],
            "bicycle": {
                "color": "red",
                "price": 19.95
            }
        },
        "expensive": 10
    }'

    次の結果が返されることが想定されます。

    OK
  2. ドキュメントをクエリします。

    クエリの例:

    ルートセレクター

    # JSON オブジェクト全体をクエリします。
    JSON.GET dockey $
    
    # 想定される出力:
    "[{"store":{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}}}]"

    ドットセレクター

    # ストア内の自転車に関するすべての情報をクエリします。
    JSON.GET dockey $.store.bicycle.*
    
    # 想定される出力:
    "["red",19.95]"
    
    # 自転車の価格をクエリします。
    JSON.GET dockey $.store.bicycle.price
    
    # 想定される出力:
    "[19.95]"

    インデックスセレクター

    # ストア内の最初の本に関するすべての情報をクエリします。
    JSON.GET dockey $.store.book[0]
    
    # 想定される出力:
    "[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}]"
    
    # ストア内のすべての本のタイトルをクエリします。
    JSON.GET dockey "$.store.book[*]['title']"
    
    # 想定される出力:
    "["Sayings of the Century","Sword of Honour","Moby Dick","The Lord of the Rings"]"

    配列スライスセレクター

    # ステップ 1 の配列スライスを使用して、ストア内の 1 番目から 3 番目の本に関するすべての情報をクエリします。
    JSON.GET dockey $.store.book[0:2:1]
    
    # 想定される出力:
    "[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]"

    子孫セレクター

    # 本と自転車の価格を含む、ストア内のすべての価格情報をクエリします。
    JSON.GET dockey $..price
    
    # 想定される出力:
    "[8.95,12.99,8.99,22.99,19.95]"

    リストセレクター

    # # ストア内の 1 番目と 3 番目の本に関するすべての情報をクエリします。
    JSON.GET dockey $.store.book[0,2]
    
    # 想定される出力:
    "[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]"

    フィルターセレクター

    # @ 式
    # ストア内で isbn 要素を持つ本に関する情報をクエリします。
    JSON.GET dockey $.store.book[?(@.isbn)]
    # 想定される出力:
    "[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]"
    
    
    # COMP 式。
    # 価格が 10 未満の本に関する情報をクエリします。
    JSON.GET dockey '$.store.book[?(@.price < 10)]'
    # 想定される出力:
    "[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]"
    
    # 複合式。
    # 価格が 12.99 と等しいか 19.95 より大きい、または category 要素の値が reference である本に関する情報をクエリします。
    JSON.GET dockey "$..book[?((@.price == 12.99 || @.price > $.store.bicycle.price) || @.category == 'reference')]"
    # 想定される出力:
    "[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]"

JSONPointer

TairDoc は、完全な JSONPointer 構文をサポートします。詳細については、「JavaScript Object Notation (JSON) Pointer」をご参照ください。

次の例は、この機能を示しています。

事前に JSON.SET doc . '{"foo": "bar", "baz" : [1,2,3]}' コマンドを実行できます。

コマンド例:

# doc キーの .baz 配列の最初の値を取得します。
JSON.GET doc /baz/0

応答例:

"1"