diff --git a/modules/n1ql/assets/images/n1ql-language-reference/ANY_SOME_EVERY_expr.png b/modules/n1ql/assets/images/n1ql-language-reference/ANY_SOME_EVERY_expr.png deleted file mode 100644 index 1a7e3972fa..0000000000 Binary files a/modules/n1ql/assets/images/n1ql-language-reference/ANY_SOME_EVERY_expr.png and /dev/null differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/ARRAY_FIRST_OBJECT_expr.png b/modules/n1ql/assets/images/n1ql-language-reference/ARRAY_FIRST_OBJECT_expr.png deleted file mode 100644 index 80639f4598..0000000000 Binary files a/modules/n1ql/assets/images/n1ql-language-reference/ARRAY_FIRST_OBJECT_expr.png and /dev/null differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/EXISTS_expr.png b/modules/n1ql/assets/images/n1ql-language-reference/EXISTS_expr.png deleted file mode 100644 index 5ff49421cc..0000000000 Binary files a/modules/n1ql/assets/images/n1ql-language-reference/EXISTS_expr.png and /dev/null differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/IN_expr.png b/modules/n1ql/assets/images/n1ql-language-reference/IN_expr.png deleted file mode 100644 index 7222ab695c..0000000000 Binary files a/modules/n1ql/assets/images/n1ql-language-reference/IN_expr.png and /dev/null differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/WITHIN_expr.png b/modules/n1ql/assets/images/n1ql-language-reference/WITHIN_expr.png deleted file mode 100644 index 5c67c20ca1..0000000000 Binary files a/modules/n1ql/assets/images/n1ql-language-reference/WITHIN_expr.png and /dev/null differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/ARRAY_expr.png b/modules/n1ql/assets/images/n1ql-language-reference/array.png similarity index 100% rename from modules/n1ql/assets/images/n1ql-language-reference/ARRAY_expr.png rename to modules/n1ql/assets/images/n1ql-language-reference/array.png diff --git a/modules/n1ql/assets/images/n1ql-language-reference/collection-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/collection-expr.png new file mode 100644 index 0000000000..45c9398151 Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/collection-expr.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/exists-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/exists-expr.png new file mode 100644 index 0000000000..c18cae0f41 Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/exists-expr.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/in-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/in-expr.png new file mode 100644 index 0000000000..21f8600fdc Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/in-expr.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/name-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/name-expr.png new file mode 100644 index 0000000000..437c669a1f Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/name-expr.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/name-var.png b/modules/n1ql/assets/images/n1ql-language-reference/name-var.png new file mode 100644 index 0000000000..dbb476a12f Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/name-var.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/range-cond.png b/modules/n1ql/assets/images/n1ql-language-reference/range-cond.png new file mode 100644 index 0000000000..078dcd11dc Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/range-cond.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/range-xform.png b/modules/n1ql/assets/images/n1ql-language-reference/range-xform.png new file mode 100644 index 0000000000..543e7dc1f2 Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/range-xform.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/range.png b/modules/n1ql/assets/images/n1ql-language-reference/range.png new file mode 100644 index 0000000000..ba60ae0ac2 Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/range.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/search-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/search-expr.png new file mode 100644 index 0000000000..437c669a1f Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/search-expr.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/target-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/target-expr.png new file mode 100644 index 0000000000..437c669a1f Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/target-expr.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/var-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/var-expr.png new file mode 100644 index 0000000000..437c669a1f Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/var-expr.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/var.png b/modules/n1ql/assets/images/n1ql-language-reference/var.png new file mode 100644 index 0000000000..dbb476a12f Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/var.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/within-expr.png b/modules/n1ql/assets/images/n1ql-language-reference/within-expr.png new file mode 100644 index 0000000000..f6ea57c8e1 Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/within-expr.png differ diff --git a/modules/n1ql/pages/n1ql-language-reference/collectionops.adoc b/modules/n1ql/pages/n1ql-language-reference/collectionops.adoc index 0dc5dab4c8..a9680fa89d 100644 --- a/modules/n1ql/pages/n1ql-language-reference/collectionops.adoc +++ b/modules/n1ql/pages/n1ql-language-reference/collectionops.adoc @@ -1,55 +1,85 @@ = Collection Operators -:description: Collection operators enable you to evaluate expressions over collections or objects. +:description: Collection operators enable you to evaluate expressions over every element in an array. :page-topic-type: concept +:page-toclevels: 2 :imagesdir: ../../assets/images +:keywords: range condition, quantified expression {description} -The operators include `ANY`, `EVERY`, `ARRAY`, `FIRST`, `EXISTS`, `IN`, and `WITHIN`. +The operators include <>, <>, and <>. -[#collection-op-any] -== ANY +NOTE: Although collection operators can be used with any array, they are particularly useful when used to evaluate expressions over an array of objects. +The term _collection_ is used here in a generic sense to refer to any array of objects, rather than in the specific sense of a xref:learn:data/scopes-and-collections.adoc[Couchbase collection]. + +[[range-cond]] +== Range Predicates -`ANY` is a range predicate that tests a Boolean condition over the elements or attributes of a collection, object, or objects. -It uses the `IN` and `WITHIN` operators to range through the collection. +Range predicates (<>, <>, or <>) enable you to test a Boolean condition over elements in an array. +They use the `IN` and `WITHIN` operators to range through the array. -=== Syntax +(((range condition))) +(((quantified expression))) +Range predicates may also be known as _range conditions_ or _quantified expressions_. -image:n1ql-language-reference/ANY_SOME_EVERY_expr.png[] +[discrete] +==== Syntax +[source,ebnf] ---- -ANY var1 ( IN | WITHIN ) expr1 - [ , var2 ( IN | WITHIN ) expr2 ]* - SATISFIES condition END +include::partial$grammar/n1ql.ebnf[tag=range-cond] ---- -=== Arguments +image::n1ql-language-reference/range-cond.png["Syntax diagram", align=left] + +[source#range-cond-binding,ebnf] +---- +include::partial$grammar/n1ql.ebnf[tag=range] +---- + +image::n1ql-language-reference/range.png["Syntax diagram", align=left] + +[discrete] +==== Arguments -var1, var2, … , varX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the variable name in the `ANY` loop. +name-var:: [Optional] An xref:n1ql-language-reference/identifiers.adoc[identifier] that represents the position of a single element in an array, counting from 0. -expr1, expr2, … , exprX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the array to loop through. +var:: An xref:n1ql-language-reference/identifiers.adoc[identifier] that represents a single element in an array. -condition:: An expression representing the limiting or matching clause to test against. +expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that returns an array to evaluate. -=== Return Values +cond:: A condition to evaluate for each specified element. +This condition may make use of the `var` and `name-var` identifiers as required. -If at least one item in the array satisfies the `ANY` expression, then it returns the entire array; otherwise, it returns an empty array. +[#collection-op-any] +=== ANY + +`ANY` tests whether any element in an array matches a specified condition. +(If the array is empty, then no element in the array is deemed to match the condition.) + +Synonym: `SOME` is a synonym for `ANY`. + +==== Return Values -=== Examples +If the array is non-empty and at least one element in the array matches the specified condition, then the operator returns `TRUE`; otherwise, it returns `FALSE`. + +==== Examples [[AnyExA]] -.ANY A +.ANY with one matching element ==== -Retrieve the array of airline flight schedules from Albuquerque (ABQ) to Atlanta (ATL) if any of the flights are after 23:40. +Retrieve the details of KL flight schedules from Albuquerque (ABQ) to Atlanta (ATL) if any of the flights are after 23:40. [source,n1ql] ---- SELECT * FROM `travel-sample`.inventory.route -WHERE airline="KL" AND sourceairport="ABQ" AND destinationairport="ATL" -AND ANY departure IN schedule SATISFIES departure.utc > "23:41" END; +WHERE airline="KL" AND sourceairport="ABQ" + AND destinationairport="ATL" + AND ANY departure IN schedule SATISFIES departure.utc > "23:40" END; ---- Since the last flight departs at 23:41, this query results in the entire array. +.Results [source,json] ---- [ @@ -67,101 +97,13 @@ Since the last flight departs at 23:41, this query results in the entire array. "flight": "KL938", "utc": "03:54:00" }, - { - "day": 0, - "flight": "KL270", - "utc": "16:57:00" - }, - { - "day": 0, - "flight": "KL222", - "utc": "05:17:00" - }, - { - "day": 0, - "flight": "KL198", - "utc": "05:07:00" - }, - { - "day": 0, - "flight": "KL858", - "utc": "18:59:00" - }, - { - "day": 1, - "flight": "KL672", - "utc": "19:19:00" - }, - { - "day": 2, - "flight": "KL832", - "utc": "15:54:00" - }, - { - "day": 2, - "flight": "KL173", - "utc": "07:18:00" - }, - { - "day": 2, - "flight": "KL520", - "utc": "09:05:00" - }, - { - "day": 3, - "flight": "KL259", - "utc": "11:05:00" - }, - { - "day": 3, - "flight": "KL065", - "utc": "17:11:00" - }, - { - "day": 4, - "flight": "KL469", - "utc": "06:06:00" - }, - { - "day": 4, - "flight": "KL509", - "utc": "06:53:00" - }, - { - "day": 4, - "flight": "KL096", - "utc": "10:29:00" - }, - { - "day": 5, - "flight": "KL347", - "utc": "08:51:00" - }, - { - "day": 5, - "flight": "KL281", - "utc": "06:26:00" - }, - { - "day": 5, - "flight": "KL567", - "utc": "03:54:00" - }, +// ... { "day": 5, "flight": "KL169", "utc": "23:41:00" }, - { - "day": 6, - "flight": "KL884", - "utc": "00:36:00" - }, - { - "day": 6, - "flight": "KL886", - "utc": "14:13:00" - }, +// ... { "day": 6, "flight": "KL636", @@ -178,10 +120,11 @@ Since the last flight departs at 23:41, this query results in the entire array. ==== [[AnyExB]] -.ANY B +.ANY with no matching elements ==== -But if you change the `SATISFIES` clause to 1 minute after the last flight ("23:42"), then the resulting array is empty. +But if you change the `SATISFIES` clause to 1 minute after the last flight (23:42), then the resulting array is empty. +.Results [source,json] ---- [] @@ -189,131 +132,57 @@ But if you change the `SATISFIES` clause to 1 minute after the last flight ("23: ==== [[AnyExC]] -.ANY C -==== -If you want to list only the matching arrays of flights instead of all the flight arrays, then see the <>. -==== - -NOTE: The `SOME` and `ANY` operators perform the same function and can be used interchangeably. - -== ARRAY - -The `ARRAY` operator lets you map and filter the elements or attributes of a collection, object, or objects. -It evaluates to an array of the operand expression, that satisfies the `WHEN` clause, if provided. - -=== Syntax - -image::n1ql-language-reference/ARRAY_FIRST_OBJECT_expr.png[] - ----- -ARRAY var1 FOR var1 ( IN | WITHIN ) expr1 - [ , var2 ( IN | WITHIN ) expr2 ]* - [ ( WHEN cond1 [ AND cond2 ] ) ] END ----- - -=== Arguments - -var1, var2, … , varX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the variable name in the `ARRAY` loop. - -expr1, expr2, … , exprX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the array to loop through. - -cond1, cond2, … , condX:: An expression representing the limiting or matching clause to test against. - -=== Return Values - -The array or arrays that satisfy the `ARRAY` expression; otherwise, it returns an empty array. - -=== Examples - -[[ArrayEx1a]] -.ARRAY A +.ANY with empty array ==== -List only the arrays of Friday night flights from Albuquerque to Atlanta after 7pm. +This example tests the ANY operator with an empty array. [source,n1ql] ---- -SELECT ARRAY v FOR v IN schedule WHEN v.utc > "19:00" AND v.day = 5 END AS fri_evening_flights -FROM `travel-sample`.inventory.route -WHERE airline="KL" AND sourceairport="ABQ" AND destinationairport="ATL" -AND ANY v IN schedule SATISFIES v.utc > "19:00" END; +SELECT ANY v IN [] SATISFIES v = "abc" END AS existential; ---- -This results in: +In this case, the operator returns `false`. +.Results [source,json] ---- [ { - "fri_evening_flights": [ - { - "day": 5, - "flight": "KL169", - "utc": "23:41:00" - } - ] + "existential": false } ] ---- ==== -[[ArrayEx1b]] -.ARRAY B -==== -The same results can be reached by writing <> as follows: - -[source,n1ql] ----- -SELECT ARRAY v FOR v IN schedule, w IN schedule WHEN v.utc > "19:00" AND w.day = 5 END AS fri_evening_flights -FROM `travel-sample` -WHERE type="route" AND airline="KL" AND sourceairport="ABQ" AND destinationairport="ATL" -AND ANY v IN schedule SATISFIES v.utc > "19:00" END; ----- -==== - [#collection-op-every] -== EVERY - -`EVERY` is a range predicate that tests a Boolean condition over the elements or attributes of a collection, object, or objects. -It uses the IN and WITHIN operators to range through the collection. - -=== Syntax - -image:n1ql-language-reference/ANY_SOME_EVERY_expr.png[] - ----- -EVERY var1 ( IN | WITHIN ) expr1 - [ , var2 ( IN | WITHIN ) expr2 ]* - SATISFIES condition END ----- - -=== Arguments - -var1, var2, … , varX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the variable name in the `EVERY` loop. +=== EVERY -expr1, expr2, … , exprX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the array to loop through. +`EVERY` tests whether every element in an array matches a specified condition. +(If the array is empty, then every element in the array is deemed to match the condition.) -condition:: An expression representing the limiting or matching clause to test against. +==== Return Values -=== Return Values +If the array is empty, or if the array is non-empty and every element in the array matches the specified condition, then the operator returns `TRUE`; otherwise, it returns `FALSE`. -If all the items in the array satisfies the `EVERY` expression, then it returns the entire array; otherwise, it returns an empty array. - -=== Examples +==== Examples [[EveryExA]] -.EVERY A +.EVERY with all matching elements ==== -Retrieve the array of airline flight schedules from Albuquerque (ABQ) to Atlanta (ATL) if all of the flights are after 00:35. +Retrieve the details of KL flight schedules from Albuquerque (ABQ) to Atlanta (ATL) if all of the flights are after 00:35. [source,n1ql] ---- SELECT * FROM `travel-sample`.inventory.route -WHERE airline="KL" AND sourceairport="ABQ" AND destinationairport="ATL" -AND EVERY departure IN schedule SATISFIES departure.utc > "00:35" END; +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL" + AND EVERY departure IN schedule SATISFIES departure.utc > "00:35" END; ---- Since the earliest flight departs at 00:36, this query results in the entire array. +.Results [source,json] ---- [ @@ -326,106 +195,13 @@ Since the earliest flight departs at 00:36, this query results in the entire arr "equipment": "757 320", "id": 36159, "schedule": [ - { - "day": 0, - "flight": "KL938", - "utc": "03:54:00" - }, - { - "day": 0, - "flight": "KL270", - "utc": "16:57:00" - }, - { - "day": 0, - "flight": "KL222", - "utc": "05:17:00" - }, - { - "day": 0, - "flight": "KL198", - "utc": "05:07:00" - }, - { - "day": 0, - "flight": "KL858", - "utc": "18:59:00" - }, - { - "day": 1, - "flight": "KL672", - "utc": "19:19:00" - }, - { - "day": 2, - "flight": "KL832", - "utc": "15:54:00" - }, - { - "day": 2, - "flight": "KL173", - "utc": "07:18:00" - }, - { - "day": 2, - "flight": "KL520", - "utc": "09:05:00" - }, - { - "day": 3, - "flight": "KL259", - "utc": "11:05:00" - }, - { - "day": 3, - "flight": "KL065", - "utc": "17:11:00" - }, - { - "day": 4, - "flight": "KL469", - "utc": "06:06:00" - }, - { - "day": 4, - "flight": "KL509", - "utc": "06:53:00" - }, - { - "day": 4, - "flight": "KL096", - "utc": "10:29:00" - }, - { - "day": 5, - "flight": "KL347", - "utc": "08:51:00" - }, - { - "day": 5, - "flight": "KL281", - "utc": "06:26:00" - }, - { - "day": 5, - "flight": "KL567", - "utc": "03:54:00" - }, - { - "day": 5, - "flight": "KL169", - "utc": "23:41:00" - }, +// ... { "day": 6, "flight": "KL884", "utc": "00:36:00" }, - { - "day": 6, - "flight": "KL886", - "utc": "14:13:00" - }, +// ... { "day": 6, "flight": "KL636", @@ -442,122 +218,301 @@ Since the earliest flight departs at 00:36, this query results in the entire arr ==== [[EveryExB]] -.EVERY B +.EVERY with no matching elements ==== -But if you change the `SATISFIES` clause to 1 minute after the first flight ("00:37"), then the resulting array is empty. +But if you change the `SATISFIES` clause to 1 minute after the first flight (00:37), then the resulting array is empty. +.Results [source,json] ---- [] ---- ==== -== EXISTS - -The `EXISTS` condition is used in combination with a subquery and is considered to be met if the subquery returns at least one result. - -It can be used in a `SELECT`, `INSERT`, `UPDATE`, or `DELETE` statement. +[[EveryExC]] +.EVERY with empty array +==== +This example tests the EVERY operator with an empty array. -=== Syntax +[source,n1ql] +---- +SELECT EVERY v IN [] SATISFIES v = "abc" END AS universal; +---- -image::n1ql-language-reference/EXISTS_expr.png[,50%] +In this case, the operator returns `true`. +.Results +[source,json] ---- -EXISTS expr +[ + { + "universal": true + } +] ---- +==== -=== Arguments +[#any-and-every] +=== ANY AND EVERY -expr:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the expression or variable being searched for. +`ANY AND EVERY` tests whether every element in an array matches a specified condition. +(If the array is empty, then no element in the array is deemed to match the condition.) -=== Return Values +Synonym: `SOME AND EVERY` is a synonym for `ANY AND EVERY`. -The `EXISTS` operator evaluates to `TRUE` if the value is an array and contains at least one element. +==== Return Values -=== Examples +If the array is non-empty and every element in the array matches the specified condition, then the operator returns `TRUE`; otherwise, it returns `FALSE`. -[[ExistsEx]] -.EXISTS +==== Examples + +[[AnyAndEveryEx]] +.ANY AND EVERY with empty array ==== -Of the 274 cities with a hotel, search for all cities that have hotels with reviews. +This example tests the ANY AND EVERY operator with an empty array. [source,n1ql] ---- -SELECT DISTINCT h.city FROM `travel-sample`.inventory.hotel AS h -WHERE EXISTS h.reviews; +SELECT ANY AND EVERY v IN [] SATISFIES v = "abc" END AS universal; ---- -This results in 255 cities that contain hotels with reviews. +In this case, the operator returns `false`. +.Results [source,json] ---- [ { - "city": "Medway" - }, - { - "city": "Giverny" - }, - { - "city": "Glasgow" - }, + "universal": false + } +] +---- +==== + +[[range-xform]] +== Range Transformations + +Range transformations (<>, <>, and <>) enable you to map and filter elements and attributes from an input array. +They use the `IN` and `WITHIN` operators to range through the array. + +[discrete] +==== Syntax + +[source,ebnf] +---- +include::partial$grammar/n1ql.ebnf[tag=range-xform] +---- + +image::n1ql-language-reference/range-xform.png["Syntax diagram", align=left] + +[source#range-xform-binding,ebnf] +---- +include::partial$grammar/n1ql.ebnf[tag=range] +---- + +image::n1ql-language-reference/range.png["Syntax diagram", align=left] + +[discrete] +==== Arguments + +name-expr:: [`OBJECT` only] An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that resolves to a string, to use as the name of an attribute in the output. +This expression may make use of the `var` and `name-var` identifiers as required. + +var-expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that returns a value to include in the output. +This expression may make use of the `var` and `name-var` identifiers as required. + +name-var:: [Optional] An xref:n1ql-language-reference/identifiers.adoc[identifier] that represents the position of a single element in an array, counting from 0. + +var:: An xref:n1ql-language-reference/identifiers.adoc[identifier] that represents a single element in an array. + +expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that returns an array to evaluate. + +cond:: [Optional] A condition to evaluate for each specified element. +This condition may make use of the `var` and `name-var` identifiers as required. + +[#array] +=== ARRAY + +The `ARRAY` operator generates a new array, using values in the input array. + +==== Return Values + +The operator returns a new array, which contains one element for each element in the input array. +If the `WHEN` clause is specified, only elements in the input array which satisfy the `WHEN` clause are considered. + +The value of each element in the output array is the output of the `var-expr` argument for one element in the input array. + +If the input array is empty, or no elements in the input array satisfy the `WHEN` clause, the operator returns an empty array. + +==== Examples + +[[ArrayEx1a]] +.ARRAY with array of objects +==== +List the details of KL flights from Albuquerque to Atlanta on Fridays. + +[source,n1ql] +---- +SELECT ARRAY v FOR v IN schedule WHEN v.day = 5 END AS fri_flights +FROM `travel-sample`.inventory.route +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL"; +---- + +.Results +[source,json] +---- +[ { - "city": "Highland" - }, -//... + "fri_flights": [ + { + "day": 5, + "flight": "KL347", + "utc": "08:51:00" + }, + { + "day": 5, + "flight": "KL281", + "utc": "06:26:00" + }, + { + "day": 5, + "flight": "KL567", + "utc": "03:54:00" + }, + { + "day": 5, + "flight": "KL169", + "utc": "23:41:00" + } + ] + } ] ---- + +Compare this with the results of <> and <>. ==== -== FIRST +[[ArrayEx1b]] +.ARRAY with multiple range terms +==== +List the details of KL flights from Albuquerque to Atlanta on Fridays after 7pm only. -The `FIRST` operator enables you to map and filter the elements or attributes of a collection, object, or objects. -It evaluates to a single element based on the operand expression that satisfies the `WHEN` clause, if provided. +[source,n1ql] +---- +SELECT ARRAY v + FOR v IN schedule, w IN schedule WHEN v.utc > "19:00" AND w.day = 5 END + AS fri_evening_flights +FROM `travel-sample`.inventory.route +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL"; +---- -=== Syntax +.Results +[source,json] +---- +[ + { + "fri_evening_flights": [ + { + "day": 5, + "flight": "KL169", + "utc": "23:41:00" + } + ] + } +] +---- + +The same results can be reached by writing the query as follows: + +[source,n1ql] +---- +SELECT ARRAY v + FOR v IN schedule WHEN v.utc > "19:00" AND v.day = 5 END + AS fri_evening_flights +FROM `travel-sample`.inventory.route +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL"; +---- +==== + +[[ArrayEx0b]] +.ARRAY with position variable +==== +List the first two KL flights from Albuquerque to Atlanta. +This example uses the position variable `i` to return just the first two elements in the input array. -image:n1ql-language-reference/ARRAY_FIRST_OBJECT_expr.png[] +[source,n1ql] +---- +SELECT ARRAY v FOR i:v IN schedule WHEN i < 2 END AS two_flights +FROM `travel-sample`.inventory.route +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL"; +---- +.Results +[source,json] ---- -FIRST var1 FOR var1 ( IN | WITHIN ) expr1 - [ , var2 ( IN | WITHIN ) expr2]* - [ ( WHEN cond1 [ AND cond2 ] ) ] END +[ + { + "two_flights": [ + { + "day": 0, + "flight": "KL938", + "utc": "03:54:00" + }, + { + "day": 0, + "flight": "KL270", + "utc": "16:57:00" + } + ] + } +] ---- -=== Arguments +Refer to <> for another example with position variables. +==== -var1, var2, … , varX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the variable name in the `ARRAY` loop. +[#first] +=== FIRST -expr1, expr2, … , exprX:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the array to loop through. +The `FIRST` operator generates a new value, using a single value in the input array. -cond1, cond2, … , condX:: An expression representing the limiting or matching clause to test against. +==== Return Values -=== Return Values +The operator returns the output of the `var-expr` argument for the first element in the input array. +If the `WHEN` clause is specified, only elements in the input array which satisfy the `WHEN` clause are considered. -The first array that satisfies the `WHEN` expression; otherwise, it returns an empty array. +If the input array is empty, or no elements in the input array satisfy the `WHEN` clause, the operator returns MISSING. -=== Examples +==== Examples [[FirstEx]] .FIRST ==== -List the first array of flights from Albuquerque to Atlanta after 7pm. +List the first KL flight from Albuquerque to Atlanta after 7pm. [source,n1ql] ---- -SELECT FIRST v FOR v IN schedule WHEN v.utc > "19:00" END AS evening_flights +SELECT FIRST v FOR v IN schedule WHEN v.utc > "19:00" END AS first_flight FROM `travel-sample`.inventory.route -WHERE airline="KL" AND sourceairport="ABQ" AND destinationairport="ATL" -AND ANY v IN schedule SATISFIES v.utc > "19:00" END; +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL"; ---- -This results in: - +.Results [source,json] ---- [ { - "evening_flights": [ + "first_flight": [ { "day": 1, "flight": "KL672", @@ -567,37 +522,174 @@ This results in: } ] ---- + +Compare this with the results of <> and <>. ==== -[#collection-op-in] -== IN +[#object] +=== OBJECT + +The `OBJECT` operator generates a new object, using values in the input array. -The `IN` operator specifies the search depth to include only the current level of an array and not to include any child or descendant arrays. +==== Return Values -=== Syntax +The operator returns an object, which contains one attribute for each element in the input array. +If the `WHEN` clause is specified, only elements in the input array which satisfy the `WHEN` clause are considered. -image::n1ql-language-reference/IN_expr.png[,50%] +The value of each attribute in the output object is the output of the `var-expr` argument for one element in the input array. + +The name of each attribute in the output object is specified by the `name-expr` argument. +This argument must be an expression that generates a unique name string for every value in the output object. +If the expression does not generate a string, then the current attribute is not output. +If the expression does not generate a unique name string for each value, then only the last attribute is output; all previous attributes are suppressed. + +The `name-expr` argument may reference the `var` argument or the `name-var` argument, or use any other expression that generates a unique value. + +If the input array is empty, or no elements in the input array satisfy the `WHEN` clause, the operator returns an empty object. + +==== Examples + +[[ObjectExA]] +.OBJECT with array of objects +==== +List the details of KL flights from Albuquerque to Atlanta on Fridays. +This example uses the xref:n1ql:n1ql-language-reference/metafun.adoc#uuid[UUID()] function to generate a unique name for each attribute in the output object. +[source,n1ql] ---- -search_expr [ NOT ] IN target_expr +SELECT OBJECT UUID():v FOR v IN schedule WHEN v.day = 5 END AS fri_flights +FROM `travel-sample`.inventory.route +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL"; ---- -=== Arguments +.Results +[source,json] +---- +[ + { + "fri_flights": { + "14c040c6-2247-442f-bc27-0d7b3ff403b5": { + "day": 5, + "flight": "KL169", + "utc": "23:41:00" + }, + "645a53d6-53a2-4c0c-9431-75073c48806b": { + "day": 5, + "flight": "KL281", + "utc": "06:26:00" + }, + "6d93a43f-ecec-4e9d-89bf-2468f2771fa0": { + "day": 5, + "flight": "KL567", + "utc": "03:54:00" + }, + "f2823bc0-86e0-4a1a-a9d8-4ca496de8193": { + "day": 5, + "flight": "KL347", + "utc": "08:51:00" + } + } + } +] +---- + +Compare this with the results of <> and <>. +==== + +[[ObjectExB]] +.OBJECT with position variable +==== +An alternative version of <>. +This example uses the xref:n1ql:n1ql-language-reference/typefun.adoc#tostring[TOSTRING()] function and the position variable `i` to generate a unique name for each attribute in the output object. + +[source,n1ql] +---- +SELECT OBJECT "num_" || TOSTRING(i):v + FOR i:v IN schedule WHEN v.day = 5 END + AS fri_flights +FROM `travel-sample`.inventory.route +WHERE airline="KL" + AND sourceairport="ABQ" + AND destinationairport="ATL"; +---- + +Notice that the position of each element in the input array is calculated _before_ applying the `WHEN` condition -- so the Friday flights are numbered from 14 to 17. + +.Results +[source,json] +---- +[ + { + "fri_flights": { + "num_14": { + "day": 5, + "flight": "KL347", + "utc": "08:51:00" + }, + "num_15": { + "day": 5, + "flight": "KL281", + "utc": "06:26:00" + }, + "num_16": { + "day": 5, + "flight": "KL567", + "utc": "03:54:00" + }, + "num_17": { + "day": 5, + "flight": "KL169", + "utc": "23:41:00" + } + } + } +] +---- + +Refer to <> for another example with position variables. +==== + +[[membership-and-existence-tests,Membership and Existence Tests]] +== Membership and Existence -search_expr:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the expression or variable being searched for. +Membership tests (<> and <>) enable you to test whether a value exists within an array. +Membership tests are efficient over arrays with a large number of elements -- up to approximately 8000. -target_expr:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the array or collection being searched through. +Existence tests enable you to test whether an array contains any elements at all. +There is one existence test: <>. -=== Return Values +[#collection-op-in] +=== IN + +The `IN` operator specifies the search depth to include only the current level of an array, and not to include any child or descendant arrays. + +==== Syntax + +[source,ebnf] +---- +include::partial$grammar/n1ql.ebnf[tag=in-expr] +---- + +image::n1ql-language-reference/in-expr.png["Syntax diagram", align=left] + +==== Arguments + +earch-expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that returns the value to search for. + +target-expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that resolves to the array to search through. + +==== Return Values The `IN` operator evaluates to `TRUE` if the right-side value is an array and directly contains the left-side value. The `NOT IN` operator evaluates to `TRUE` if the right-side value is an array and does not directly contain the left-side value. -=== Examples +==== Examples [[InExA]] -.IN A +.IN with simple array ==== Search for all airlines from the United Kingdom or France. @@ -609,6 +701,7 @@ WHERE country IN ["United Kingdom", "France"]; This results in 60 documents: +.Results [source,json] ---- [ @@ -629,17 +722,18 @@ This results in 60 documents: ==== [[InExB]] -.IN B +.IN with array of objects ==== -Search for the author "Walton Wolf" in the hotel documents. +Search for the author "Walton Wolf" in the hotel keyspace. [source,n1ql] ---- SELECT * FROM `travel-sample`.inventory.hotel AS t WHERE "Walton Wolf" IN t; ---- -This results in an empty set because authors are not in the current level (the root level) of the `travel-sample` documents. +This results in an empty set because authors are not in the current level (the root level) of the hotel keyspace. +.Results [source,json] ---- [] @@ -649,31 +743,32 @@ The authors are listed inside the `reviews` array (a child element) and would ne ==== [#collection-op-within] -== WITHIN - -The `WITHIN` operator specifies the search depth to include the current level of an array and all of its child and descendant arrays. +=== WITHIN -=== Syntax +The `WITHIN` operator specifies the search depth to include the current level of an array, and all of its child and descendant arrays. -image::n1ql-language-reference/WITHIN_expr.png[,50%] +==== Syntax +[source,ebnf] ---- -search_expr [ NOT ] WITHIN target_expr +include::partial$grammar/n1ql.ebnf[tag=within-expr] ---- -=== Arguments +image::n1ql-language-reference/within-expr.png["Syntax diagram", align=left] + +==== Arguments -search_expr:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the expression or variable being searched for. +search-expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that returns the value to search for. -target_expr:: A string or xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that evaluates to a string representing the array or collection being searched through. +target-expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that resolves to the array to search through. -=== Return Values +==== Return Values -The `WITHIN` operator evaluates to `TRUE` if the right-side value is an array and directly contains the left-side value as a child or descendant, that is, directly or indirectly. +The `WITHIN` operator evaluates to `TRUE` if the right-side value is an array and contains the left-side value as a child or descendant, that is, directly or indirectly. The `NOT WITHIN` operator evaluates to `TRUE` if the right-side value is an array and no child or descendant contains the left-side value. -=== Examples +==== Examples [[WithinEx]] .WITHIN @@ -687,6 +782,7 @@ SELECT * FROM `travel-sample`.inventory.hotel AS t WHERE "Walton Wolf" WITHIN t; This results in 1 document since his name appears inside the `reviews` array. +.Results [source,json] ---- [ @@ -721,58 +817,7 @@ This results in 1 document since his name appears inside the `reviews` array. "reviews": [ { "author": "Walton Wolf", - "content": "Myself and a mate stayed here the last week of April 2010. On arrival were were told that the travel agent booked us a king bed and not a double room as we requested when booking and made sure it was a double, as 2 blokes. the guy on reception was not moving on it, he said there will be a double room available on the tuesday, this was sunday when we came. he also advised us that it will be an extra 20 dollars per night in the double room. in fairness we were not impressed with his attitude and inflexibility. nothing we could do so we jst grinned and beared it. then to make things worse, our room was in the basement, beside the breakfeast room and the ice machines and vending machines. Pure pissed off afer paying 500euro each for this $@!#%. The room was serioulsy small, no room for our suitcases, a major squash round the king bed. pure noisy the following morning frm the machines outside our room, this should not be a room it should be a storage room, so not impressed. After one night in that room we asked the girl on reception if ther is any chance we could change room to a double, she checked and said yes, one is available and they are jst cleaning it and after that we can change room. Obviously the guy on reception the day b4 jst cudnt be bothered informing us of this. After we chaged rooms it was fine, room was ok for ny, not alot of space to move about, have stayed in better ones in ny. had no problem after we changed rooms, the girl on reception was very nice and helpful, she let me do check my online banking on her pc and let us use the phone when we neede to, at no cost, she couldnt be more nice. Love ny, done all the usual haunts and sites, grand location, great italian restaurant a few mins walk away, great food, and u get a discount when u mention u are staying in the gem hotel, the girl on reception gave us a card for the restaruant. What more can i say, the hotel was fine after the inital ignorance, our stay was more pleasant chatting away to the nice girl on reception, whos name i cant remember lol, long culry dark hair ha ha.", - "date": "2014-06-07 03:54:50 +0300", - "ratings": { - "Cleanliness": 4, - "Location": 4, - "Overall": 4, - "Rooms": 2, - "Service": 3, - "Sleep Quality": 4, - "Value": 3 - } - }, - { - "author": "Catharine Funk", - "content": "My first trip to new york city was a disaster because of this hotel. My wedding is only 2 months away and my fiance and I have bed bug bites all over our body. (30+ bites each) I'm hoping the 6 welts on my face won't scar before our wedding day. The guy that was working there that night helped us find a different hotel. He was really kind. But who wants to stay at a staff friendly bed bug infested hotel? I should have known better to not book a room that's $114 a night. Do yourself and your family a favor and do NOT go to this hotel no matter what cheap rate they offer.", - "date": "2012-01-02 21:29:27 +0300", - "ratings": { - "Cleanliness": 1, - "Location": 2, - "Overall": 1, - "Rooms": 1, - "Service": 5, - "Sleep Quality": 1, - "Value": 3 - } - }, - { - "author": "Tavares Denesik", - "content": "This was my second time to stay at this hotel. Although my stay was for only two days, I felt very comfortable there. More like an exclusive appartment than a hotel. The flat was small but extreamly adequate. I enjoyed my stay whilst saving BIG money. My next business trip to NYC I will definately stay there.", - "date": "2014-03-27 18:11:46 +0300", - "ratings": { - "Cleanliness": 5, - "Location": 5, - "Overall": 5, - "Rooms": 4, - "Service": 5, - "Value": 5 - } - }, - { - "author": "Lucy Graham", - "content": "SUMMARY - Although the GEM Hotel is associated with the Choice Hotels chain (Quality, Comfort, Econo, etc.) this is the first time I've heard of this particular branding. They are billed as a \"Botique Hotel\" and certainly fit the bill as much as a chain can be considered a \"Botique\". The place is very bare bones and minimal, yet very stylish and modern. They just give you the very basics of what you need and not much else, but the price reflects that. So it's hard to complain. There are 10 floors and approximately 4 small rooms/floor. It's not the kind of place I'd spend a whole week because it's rather small, has limited storage, and very few of the \"extras\" you'd need for an extended stay. But for staying a night or two in NYC when you just need a place to sleep and shower it does just fine. I forgot to take photos this time, but as of today the photos the hotel has provided on various travel websites are fairly accurate. You just have to take a close look at them to see how small the space really is and understand that the photos really show the WHOLE room. There's not much cropped out! BATHROOM: Clean, basic, and modern. It was pretty much a standard hotel sized bathroom, even though the main room was small. BEDS: Two double beds. Very comfortable, leaning towards the soft side of hotel beds. Sheets were clean and more modern/stylish than you'd find in most chain hotels. BILLING: Reserved via choicehotels.com only a few days ahead of time. The front desk had no problems getting us checked in, and the taxes/surcharges only added up to another 16% of the cost of the room itself. BREAKFAST: There is free coffee/tea in the room, but i never looked for a continental breakfast. There were vending machines in the basement with the ice/water machine. CLEANING: The room was as clean as it gets. While the building is obviously old, it seems that the entire interior is brand new. CLIMATE CONTROL: There was a brand new heater/air conditioning unit that was very quiet and easily adjustable. ELEVATORS: One main, new looking elevator in the lobby. It worked just fine and was fairly large. FRONT DESK: The front desk was helpful and competent. We had to wait about 15-20 minutes for a room to be cleaned. They may have had the smallest, most basic lobby i've ever seen in my life. But if you're looking for water fountains and gold trim you're not going to get it in a hotel with sub-$200 rates! GYM: None. HOT TUB: None. INTERNET: Didn't try it. I was too busy enjoying the city. LOCATION: On the west-side on 36th very close to the corner of 10th. It's a much more sparsely populated and quiet area than most of Manhattan, as it borders on more of an industrial zone. However, it's only a few blocks to Times Square, Penn Station, and Madison Square Garden. It's a block from the entrace to the Lincoln Tunnel. It was nice to be so close to everything, yet just off the \"beaten path\" in a calmer area. There's a gas station on the corner (one of the few in Manhattan) and a few other random bodegas and restaurants nearby. NOISE: It's NYC, there's always going to be some noise, but there was nothing excessive. Lots of trucks roll down 10th avenue at night, but they mostly just blended into the background. PARKING: None. It's best to find a park & ride outside the city and take a train in. Penn Station is just 2 short blocks and then 2 long blocks away. POOL: None. RECREATION: None. RESTAURANT: None, but it's New York. I'm sure you can find something to eat. For the less adventurous, I did notice a McDonald's on 10th, just a short walk from the hotel. ROOM: The room was small and there wasn't much room around the beds. I'll admit, for 3 people, it was a bit cramped. If you like your space I'd limit occupancy to 2 or find another, bigger, hotel. There was limited storage, just one small wardrobe with 2 drawers underneath, a small nightstand, alarm clock/ipod player, desk, desk chair, and flat screen TV. Again, the decor was very modern. SHUTTLE: None. STORE: None on site, a gas station on the corner, several bodegas nearby. SUPPLIES: Standard Soap, Shampoo, Conditioner, Mouthwash & Towels. ===== ===== ===== RATING NOTE: My ratings are generally based on value vs money. Thus, sometimes a simple hotel will receive a 4 or 5, while a fancy hotel can rank a 1 or 2 if I don't feel it was worth the cost. Also, a hotel can do everything right and still only rank as a 4, unless there's something really exceptional about it. 5 = Hotel gets everything right, and goes above and beyond. 4 = Hotel gets everything right. 3 = Hotel is acceptable value for money spent. 2 = Hotel isn't worth the money spent. 1 = Hotel should pay ME to stay there.", - "date": "2014-09-30 09:41:30 +0300", - "ratings": { - "Check in / front desk": 3, - "Cleanliness": 4, - "Location": 4, - "Overall": 4, - "Rooms": 3, - "Service": 3, - "Value": 5 - } +// ... } ], "state": null, @@ -786,3 +831,65 @@ This results in 1 document since his name appears inside the `reviews` array. ] ---- ==== + +[#exists] +=== EXISTS + +The `EXISTS` operator enables you to test whether an array has any elements, or is empty. + +This operator may be used in a `SELECT`, `INSERT`, `UPDATE`, or `DELETE` statement in combination with a subquery. +The condition is met if the subquery returns at least one result. + +==== Syntax + +[source,ebnf] +---- +include::partial$grammar/n1ql.ebnf[tag=exists-expr] +---- + +image::n1ql-language-reference/exists-expr.png["Syntax diagram", align=left] + +==== Arguments + +expr:: An xref:n1ql-language-reference/index.adoc#N1QL_Expressions[expression] that returns an array. + +==== Return Values + +If the expression is an array which contains at least one element, the operator evaluates to `TRUE`; otherwise, it evaluates to `FALSE`. + +==== Examples + +[[ExistsEx]] +.EXISTS +==== +Of the 274 cities with a hotel, search for all cities that have hotels with reviews. + +[source,n1ql] +---- +SELECT DISTINCT h.city +FROM `travel-sample`.inventory.hotel AS h +WHERE EXISTS h.reviews; +---- + +This results in 255 cities that contain hotels with reviews. + +.Results +[source,json] +---- +[ + { + "city": "Medway" + }, + { + "city": "Giverny" + }, + { + "city": "Glasgow" + }, + { + "city": "Highland" + }, +//... +] +---- +====