基本
エスケープ文字
ユーザー定義語句(バケット名、フィールド名)は、「`」を使ってエスケープすることによって、予約語との衝突を回避することができます。
Couchbase Serverでは、「-」は、予約語に含まれるため、「-」を含むバケット名を利用する場合、下記のようにバケット名をエスケープする必要があります。
SELECT ... FROM `travel-sample`
構造
N1QLは、JSONデータを構成する文字列、数値、真偽値を(直接的に、つまり文字列としてエスケープされた形ではなく)含むことができます。以下に具体的な例を見てみます。
コンストラクションオペレーター
以下の記号は、コンストラクションオペレーターと呼ばれます。
{
, }
, :
, [
, ]
ネステッドオペレーター・エクスプレッション
以下の表現は、ネステッドオペレーター・エクスプレッションと呼ばれrます。
- ドットノーテーション (
.
) - 配列表現(インデックス、スライス)
ドキュメントキー
USE KEYS
SELECT *
FROM `travel-sample`
USE KEYS "airport_1254";
SELECT *
FROM `travel-sample`
USE KEYS ["airport_1254","airport_1255"];
USE KEYS
のみを利用してクエリを行う場合、インデックスを作成する必要がありません。
注意: Couchbase Serverでは、ドキュメントキーが判明している場合には、ドキュメントキーを指定してドキュメントを取り出すことが、(RDBにおける、主キーでの検索のように)最も効果的であることは間違いありません。一方でドキュメントキーが判明しているケースにおいては、性能を追求する場合、必ずしもクエリ用いて(Queryサービスを介して)ドキュメントを取り出す必要はなく、Dataサービスに対して直接リクエストすることで性能を最適化することが可能です(特に上記の例のような単純な利用の場合。一方、サブクエリを伴うような複雑なクエリの場合など、USE KEYS
句を効果的に利用できる場面があります)。
META().id
上記のUSE KEYS
を利用したクエリは、下記のようにMETA().id
を使って書き直すことができます。
SELECT *
FROM `travel-sample`
WHERE META().id IN ["airport_1254","airport_1255"];
META().id
を利用してクエリを行う場合、META().id
を用いたインデックスが作成されている必要があります。
USE KEYS
の構文では、後続する鉤括弧の中のドキュメントキーは完全一致が想定されていますが、META().id
を利用する場合、N1QLクエリの一部として、LIKE
と組み合わせることができ部分一致検索を行うことができる他、比較演算子による大小比較など、クエリの名で用いる際により自由度が高い表現と言えます。
また、検索条件としてのみではなく、SELECT META().id FROM ... WHERE ...
のように、条件に一致するドキュメントキーを検索するために用いることもできます。
上記のクエリ中のMETA().id
の部分は、下記のように、バケット名を含んだ表現を用いることができます。このクエリのように、クエリの中でキースペース(バケット名)が一意に決まっている場合、指定は必須ではありません。複数のキースペースが混在している中で、ドキュメントのキーを用いる(取り出す)場合には、キースペースを指定した表現を用います。
SELECT *
FROM `travel-sample`
WHERE META(`travel-sample`).id IN ["airport_1254","airport_1255"];
N1QLキーワード
フィールドの操作
RAW
| ELEMENT
| VALUE
これらは全て同義語です(以下では、RAW
を用います)。
N1QLで検索された結果は、JSONデータとして、フィールド名と値のペアとなることが基本ですが、RAW
キーワードをSELECT
句と共に用いることで、JSONデータの値のみを取り出すことができます。
RAW
を用いない例
クエリ
SELECT city
FROM `travel-sample`
WHERE type = "airport"
ORDER BY city
LIMIT 5;
結果
[
{ "city": "Abbeville" },
{ "city": "Aberdeen" },
{ "city": "Aberdeen" },
{ "city": "Aberdeen" },
{ "city": "Abilene" }
]
RAW
を用いた例
クエリ
SELECT RAW city
FROM `travel-sample`
WHERE type = "airport"
ORDER BY city
LIMIT 5;
結果
[
"Abbeville",
"Aberdeen",
"Aberdeen",
"Aberdeen",
"Abilene„
]
DISTINCT
と組み合わせた利用例
SELECT DISTINCT RAW city
FROM `travel-sample`
WHERE type="airport"
ORDER BY city LIMIT 5;
[
"Abbeville",
"Aberdeen",
"Abilene",
"Adak Island",
"Addison"
]
配列
コレクション形データを操作するための、コレクションオペレーターとして以下があります。
ANY
, EVERY
, ARRAY
, FIRST
, EXISTS
, IN
, WITHIN
選択項目としての配列利用
ARRAY
またはFIRST
から始まり、END
で基本単位となります。
IN
またはWITHIN
とFOR
により、コレクションの要素へのループを表現しています。
( ARRAY | FIRST ) var1 FOR var1 ( IN | WITHIN ) expr1 END
WHEN
句により、条件指定を付け加えることが可能です。
( ARRAY | FIRST ) var1 FOR var1 ( IN | WITHIN ) expr1 [ ( WHEN cond1 [ AND cond2 ] ) ] END
下記の通り、,
により、上記説明した内容を複数並べて用いることができます。
( ARRAY | FIRST ) var1 FOR var1 ( IN | WITHIN ) expr1
[ , var2 ( IN | WITHIN ) expr2 ]*
[ ( WHEN cond1 [ AND cond2 ] ) ] END
検索条件としての配列利用
ANY
またはEVERY
から始まり、END
までで基本単位となります。SATISFIES
で条件を指定します。
( ANY | EVERY ) var1 ( IN | WITHIN ) expr1
[ , var2 ( IN | WITHIN ) expr2 ]*
SATISFIES condition END
注意: この構文は、配列から、真となった要素を取り出しているのではないことに注意してください。これは、SQLのWHERE条件が検索に使ったカラムを取り出すものではないのと同様です。
ANY
配列に条件で指定した要素が一つでも含まれる場合、真となります。
SELECT *
FROM purchases
WHERE ANY item IN purchases.lineItems SATISFIES
item.count >= 5 END
EVERY
配列の全ての要素が、指定した条件に一致する場合、真となります。
SELECT *
FROM purchases
WHERE EVERY item IN purchases.lineItems SATISFIES
item.count >= 5 END
IN
またはWITHIN
IN
句が、指定された配列のトップレベルの要素を検索するのに対して、WITHIN
句は、現在の配列とその子、および子孫を含めて検索対象とします。
ドキュメントキーによる結合 : NEST
NEST
は、外部の子ドキュメントを親の下に埋め込む特別なタイプのJOIN
です。
ドキュメント・キーを介した参照関係でデータをモデル化した際に用いる事ができます。ON KEYS
により、対象とするドキュメントのキーを指定することができます。
{"order_id":1234,
"type":"Order",
"customer_id":"34567",
"total_price":"65.5",
"lineitems":["o11","o12","o13"]
}
{"lineitem_id":o11,
"type":"lineitem",
"item_id":"789",
"qty":"3",
"itemprice":"5.99",
"base_price":"17.97",
"tax":"0.75",
"total_price":"18.22"
}
{"lineitem_id":o12,
"type":"lineitem",
"item_id":"234",
"qty":"5",
"itemprice":"10.00",
"base_price":"50.00",
"tax":"0.75",
"total_price":"50.75"
}
SELECT ordr.order_id,
ARRAY {“item_id”: l.item_id, “quantity”:l.qty} FOR l IN line END as items
FROM `retailsample` ordr
NEST `retailsample` line
ON KEYS ordr.lineitems
結果は、下記のように、一つのドキュメントになります。
[
{
"items":[
{"item_id":"789", "qty":"3"},
{"item_id":"234", "qty":"5"}
];
"order_id":"1234"
},
{
"items":[
{"item_id":"899", "qty":"8"},
{"item_id":"651", "qty":"2"}
];
"order_id":"9812"
},
]
サブドキュメントのフラット化: UNNEST
UNNEST
は、ネストされたオブジェクトを最上位ドキュメントとして表示するために用います。
下記のようなネストされた構造を持つデータを想定します(受注明細データを中に含む受注伝票データ)。
{
"ordId": "ORDER-0001",
"status": "Shipped",
"items": [
{
"prodId": "AAA-222",
"qty": 1
},
{
"prodId": "BBB-333",
"qty": 2
},
{
"prodId": "CCC-444",
"qty": 3
}
]
}
UNNEST
は、このようなネストされた(サブドキュメントを含む)ドキュメントへのクエリの結果を下記のようなテーブル構造として利用したい時に使われます。
ordId | Status | prodId | qty |
---|---|---|---|
ORDER-0001 | Shipped | AAA-222 | 1 |
ORDER-0001 | Shipped | BBB-333 | 2 |
ORDER-0001 | Shipped | CCC-444 | 3 |
クエリでは、UNNEST
をサブドキュメントに対して指定し、as
で別名をつけたものをSELECT
句の中で使用します。
SELECT ord.ordId, ord.status, item.* FROM orders ord UNNEST items as item
下記のようなフラットな構造のJSONが取り出されます。
[
{ “ordId”: “ORDER-0001”, “status”: “Shipped”, “prodId”: “AAA-222”, “qty”: 1 },
{ “ordId”: “ORDER-0001”, “status”: “Shipped”, “prodId”: “BBB-333”, “qty”: 2 },
{ “ordId”: “ORDER-0001”, “status”: “Shipped”, “iprodId”: “CCC-444”, “qty”: 3 }
]
(JSON中の要素の出現順はこの通りではありません)
情報: JSONオブジェクトのフィールドは並び順に意味を持ちません。
SQLと比べた場合の制約
-
FULL [OUTER] JOIN
はサポートされていません -
CROSS JOIN
はサポートされていません -
RIGHT [OUTER] JOIN
は、JOIN連結の最初の (または唯一の) クエリである必要があります
参考情報:コミュニティエディションとエンタープライズエディションの違い
クエリに関連した、コミュニティエディションには含まれない、エンタープライズエディションの機能として、以下があります。
機能
- ウィンドウ関数
- FLEXインデックス(クエリからの全文検索インデックス利用)
性能・最適化
- コストベースオプティマイザ(CBO)
- 無制限のクエリ同時実行
- N1QLアグリゲートプッシュダウン
マネジメント
- N1QLリクエストの監査
- クエリのモニタリング