From 78d4535d21980c678b9f767e8fbb942c7c410d29 Mon Sep 17 00:00:00 2001 From: cbullinger Date: Tue, 21 May 2024 15:03:18 -0400 Subject: [PATCH] RQL page updates --- .../__tests__/realm-query-language.test.ts | 64 +- ...t.snippet.arithmetic-obj-properties.ts.rst | 3 - ...nippet.nil-type-parameterized-query.ts.rst | 4 - .../query-engines/realm-query-language.txt | 900 +++--------------- 4 files changed, 164 insertions(+), 807 deletions(-) delete mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.arithmetic-obj-properties.ts.rst delete mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type-parameterized-query.ts.rst diff --git a/examples/node/v12/__tests__/realm-query-language.test.ts b/examples/node/v12/__tests__/realm-query-language.test.ts index fc7fa248d6..97dccebb9f 100644 --- a/examples/node/v12/__tests__/realm-query-language.test.ts +++ b/examples/node/v12/__tests__/realm-query-language.test.ts @@ -201,12 +201,22 @@ describe("Realm Query Language Reference", () => { test("Dot notation", () => { const address = realm.objects(Project); - const nestedMatch = address.filtered( + const nestedItem = address.filtered( + // :snippet-start: dot-notation + // Find projects whose `items` list property contains + // an Item object with a specific name. + "items[0].name == 'Approve project plan'" + // :snippet-end: + ); + const nestedZipcode = address.filtered( // :snippet-start: deep-dot-notation + // Find projects whose `projectLocation` property contains + // an embedded Address object with a specific zip code. "projectLocation.address.zipcode == 10019" // :snippet-end: ); - expect(nestedMatch.length).toBe(3); + expect(nestedItem.length).toBe(2); + expect(nestedZipcode.length).toBe(3); }); }); @@ -222,15 +232,6 @@ describe("Realm Query Language Reference", () => { ); expect(highPriorityItems.length).toBe(5); - const longRunningItems = items.filtered( - // :remove-end: - - // Compare `progressMinutes` values against a threshold value. - "progressMinutes > $0", 120 - // :remove-start: - ); - expect(longRunningItems.length).toBe(1); - const unassignedItems = items.filtered( // :remove-end: @@ -250,13 +251,12 @@ describe("Realm Query Language Reference", () => { expect(progressMinutesRange.length).toBe(2); const progressMinutesIn = items.filtered( - // :remove-end: + // :remove-end: // Compare `progressMinutes` values against any of the listed values. "progressMinutes IN { $0, $1, $2 }", 10, 30, 60 // :snippet-end: ); - expect(progressMinutesIn.length).toBe(2); }); // prettier-ignore @@ -284,14 +284,14 @@ describe("Realm Query Language Reference", () => { const items = realm.objects(Item); const basicMath = items.filtered( // :snippet-start: basic-arithmetic - // Find items with a `priority` greater than 3. - "2 * priority > 6" // `priority > 3` + // Evaluate against an item's `priority` property value: + "2 * priority > 6" // resolves to `priority > 3` // :remove-start: ); const lessBasicMath = items.filtered( // :remove-end: - "priority >= 2 * (2 - 1) + 2" // `priority >= 4` - // :snippet-end: + "priority >= 2 * (2 - 1) + 2" // resolves to `priority >= 4` + // :remove-start: ); expect(basicMath.length).toBe(6); expect(lessBasicMath.length).toBe(6); @@ -300,7 +300,9 @@ describe("Realm Query Language Reference", () => { test("Arithmetic with object properties", () => { const items = realm.objects(Item); const mathWithObjProps = items.filtered( - // :snippet-start: arithmetic-obj-properties + // :remove-end: + + // Evaluate against multiple object property values: "progressMinutes * priority == 90" // :snippet-end: ); @@ -466,6 +468,7 @@ describe("Realm Query Language Reference", () => { test("Sort, distinct, and limit results", () => { const items = realm.objects(Item); + const projects = realm.objects(Project); const sortedUniqueAliItems = items.filtered( // :snippet-start: sort-distinct-limit @@ -474,6 +477,24 @@ describe("Realm Query Language Reference", () => { ); expect(sortedUniqueAliItems.length).toBe(1); + const query = + // :snippet-start: sort-distinct-limit-order-matters + "SORT(priority DESC) LIMIT(2) DISTINCT(name)"; + // Returns 2 items with the highest priority + // :remove-start: + const orderMatters = items.filtered( + "isComplete != true SORT(priority DESC) LIMIT(2) DISTINCT(name)" + ); + expect(orderMatters.length).toBe(2); + const query2 = + // :remove-end: + "isComplete != true DISTINCT(name) SORT(priority DESC) LIMIT(2)"; + // Returns the first 2 uniquely named items with the highest priority + // :snippet-end: + const limitFirst = items.filtered( + "isComplete != true DISTINCT(name) SORT(priority DESC) LIMIT(2)" + ); + console.log(limitFirst.toJSON()); }); test("Subquery queries", () => { @@ -711,12 +732,13 @@ describe("Realm Query Language Reference", () => { const res = items.filtered( // :snippet-start: nil-type "assignee == nil" - // :snippet-end: + // :remove-start: ); // prettier-ignore const res2 = realm.objects(Item).filtered( - // :snippet-start: nil-type-parameterized-query - // comparison to language null pointer + // :remove-end: + + // 'null' maps to the SDK language's null pointer "assignee == $0", null // :snippet-end: ); diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.arithmetic-obj-properties.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.arithmetic-obj-properties.ts.rst deleted file mode 100644 index 24d0f66896..0000000000 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.arithmetic-obj-properties.ts.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. code-block:: typescript - - "progressMinutes * priority == 90" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type-parameterized-query.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type-parameterized-query.ts.rst deleted file mode 100644 index 6f376e9336..0000000000 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type-parameterized-query.ts.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. code-block:: typescript - - // comparison to language null pointer - "assignee == $0", null diff --git a/source/sdk/crud/query-engines/realm-query-language.txt b/source/sdk/crud/query-engines/realm-query-language.txt index a7c2cdd014..3eb1f675e5 100644 --- a/source/sdk/crud/query-engines/realm-query-language.txt +++ b/source/sdk/crud/query-engines/realm-query-language.txt @@ -1,23 +1,30 @@ .. _realm-query-language: .. _rql: -==================== -Realm Query Language -==================== +========================== +Realm Query Language (RQL) +========================== .. meta:: - :description: Learn how to use Realm Query Language (RQL) to retrieve objects from the database. - -.. facet:: - :name: genre + :description: Use Realm Query Language (RQL) to retrieve objects from the database. + :keywords: Realm, Flutter SDK, Kotlin SDK, Java SDK, Node.js SDK, code example, filter, search + +.. facet:: + :name: genre :values: reference +.. facet:: + :name: programming_language + :values: cpp, csharp, dart, java, javascript/typescript, kotlin + .. contents:: On this page :local: :backlinks: none :depth: 3 :class: singlecol +.. tabs-selector:: drivers + Realm Query Language (RQL) is a string-based query language to constrain searches when retrieving objects from a realm. SDK-specific methods pass queries to the Realm query engine, which retrieves matching objects from the realm. @@ -42,7 +49,7 @@ documentation: - :ref:`Fluent Interface (Java SDK) ` - :ref:`LINQ (.NET SDK) ` - :ref:`Type-Safe and NSPredicate Queries (Swift SDK) ` - + .. note:: Swift SDK does not support Realm Query Language The Swift SDK does not support querying with Realm Query Language. @@ -67,250 +74,78 @@ The two Realm object types are ``Project`` and ``Item``. See the schema for these two classes, ``Project`` and ``Item``, below: -.. tabs:: - - .. tab:: Java SDK - :tabid: java - - .. tabs-realm-languages:: - - .. tab:: - :tabid: java - - .. code-block:: java - - public class Item extends RealmObject { - ObjectId id = new ObjectId(); - String name; - Boolean isComplete = false; - String assignee; - Integer priority = 0; - Integer progressMinutes = 0; - @LinkingObjects("items") - final RealmResults projects = null; - } - public class Project extends RealmObject { - ObjectId id = new ObjectId(); - String name; - RealmList items; - Integer quota = null; - } - - .. tab:: - :tabid: kotlin - - .. code-block:: kotlin - - open class Item(): RealmObject() { - var id: ObjectId = new ObjectId() - @FullText - lateinit var name: String - var isComplete: Boolean = false - var assignee: String? = null - var priority: Int = 0 - var progressMinutes: Int = 0 - } - - open class Project(): RealmObject() { - var id: ObjectId = new ObjectId() - lateinit var name: String - lateinit var items: RealmList - var quota: Int? = null - } - - .. tab:: .NET SDK - :tabid: dotnet - - .. literalinclude:: /examples/generated/dotnet/RqlSchemaExamples.snippet.rql-schema-examples.cs - :language: csharp - - .. tab:: Node.js SDK - :tabid: node - - .. literalinclude:: /examples/generated/node/rql-data-models.snippet.rql-data-models.js - :language: javascript +.. include:: /includes/sdk-examples/crud/query/rql/rql-example-data-model.rst - .. tab:: React Native SDK - :tabid: react-native - .. literalinclude:: /examples/generated/node/rql-data-models.snippet.rql-data-models.js - :language: javascript +Query Syntax +------------ - .. tab:: Kotlin SDK - :tabid: kotlin - .. literalinclude:: /examples/generated/kotlin/RQLTest.snippet.rql-schema-example.kt - :language: kotlin - .. tab:: Flutter SDK - :tabid: Flutter +Dot Notation +~~~~~~~~~~~~ - .. literalinclude:: /examples/generated/flutter/task_project_models_test.snippet.task-project-models.dart - :language: dart +You can use **dot notation** to refer to child properties of an object, including the properties of embedded objects and relationships: -Expressions ------------ +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.dot-notation.ts.rst -Filters consist of **expressions** in a predicate. An expression consists of -one of the following: +You can also chain dot notations for nested properties. +For example, each Project has a ``projectLocation`` property that +refers to an Office object, which itself contains an embedded object +property ``address``. You can chain dot notations to query the deeply nested +``zipcode`` property of an embedded address: -- The name of a property of the object currently being evaluated. -- An operator and up to two argument expression(s). For example, in the - expression ``A + B``, the entirety of ``A + B`` is an expression, but ``A`` - and ``B`` are also argument expressions to the operator ``+``. -- A value, such as a string (``'hello'``) or a number (``5``). +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.deep-dot-notation.ts.rst -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.predicate.js - :language: javascript +.. TODO: add as part of collections-in-mixed epic +Bracket Notation +~~~~~~~~~~~~~~~~ .. _rql-parameterized-queries: -Parameterized Queries ---------------------- - -Create parameterized queries to interpolate variables into prepared -Realm Query Language statements. The syntax for interpolated variables is -``$``, starting at ``0``. Pass the positional arguments as -additional arguments to Realm SDK methods that use Realm Query Language. - -Include just one parameter with ``$0``. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.predicate.js - :language: js - -Include multiple parameters with ascending integers starting at ``$0``. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.multiple-predicate.js - :language: js +Parameterized vs. Serialized Queries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Query Formats -~~~~~~~~~~~~~ +You can format queries in two ways: -The following table shows how a query should be formatted when serialized and -parameterized for the following data types: +- **Serialized queries** pass values directly in the expression. -.. list-table:: - :header-rows: 1 - :widths: 15 25 25 35 - - * - Type - - Parameterized Example - - Serialized Example - - Note - - * - Boolean - - "setting == $0", false - - "setting == false" - - ``true`` or ``false`` values. - - * - :ref:`String ` - - "name == $0", "George" - - "name == 'George'" - - Applies to ``string`` and ``char`` data type. - - * - :ref:`Number ` - - "age > $0", 5.50 - - "age > 5.50" - - Applies to ``int``, ``short``, ``long``, ``double``, ``Decimal128``, and ``float`` data types. - - * - :ref:`Date ` - - "date < $0", dateObject - - "date < 2021-02-20\@17:30:15:0" - - For parameterized date queries, you must pass in a date object. - For serialized date queries, you can represented the date in the following formats: - - - As an explicit date and time- YYYY-MM-DD\@HH:mm:ss:nn - (year-month-day@hours:minutes:seconds:nanoseconds) - - As a ``datetime`` relative to the :wikipedia:`Unix epoch `- Ts:n - (T, designates the start of the time; ``s``, seconds; ``n``, nanoseconds) - - Parameterized ``Date`` object - - * - :ref:`ObjectID ` - - "_id == $0", oidValue - - "_id == oid(507f1f77bcf86cd799439011)" - - For parameterized ObjectId queries, you must pass in an ObjectId. - For serialized ObjectId queries, the string representation is ``oid()``. - - * - :ref:`UUID ` - - "id == $0", uuidValue - - "id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)" - - For parameterized UUID queries, you must pass in a UUID. - For serialized UUID queries, the string representation is ``uuid()``. - - * - Binary - - "value == $0", "binary" - - "value == 'binary'" - - For ASCII characters, RQL serializes the binary value like a string, - with quotes. For non-printable characters, - RQL serializes the binary to a base 64 value. - - * - :ref:`List ` - - "ANY items.name == {$0, $1}", "milk", "bread" - - "ANY items.name == {'milk', 'bread'}" - - Applies for list, collections, and sets. A parameterized value should be used - for each member of the list. - - * - RealmObject - - "ANY items == $0", obj("Item", oid(6489f036f7bd0546377303ab)) - - "ANY items == obj('Item', oid(6489f036f7bd0546377303ab))" - - To pass in a RealmObject, you need the class and primary key of the object. - -.. _rql-dot-notation: - -Dot Notation ------------- +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.serialized-query.ts.rst -When referring to an object property, you can use **dot notation** to refer -to child properties of that object. You can even refer to the properties of -embedded objects and relationships with dot notation. +- **Parameterized queries** pass interpolated variables as additional + arguments. The syntax for interpolated variables is + ``$``, starting at ``0`` and incrementing for each additional variable. -For example, consider a query on an object with a ``workplace`` property that -refers to a Workplace object. The Workplace object has an embedded object -property, ``address``. You can chain dot notations to refer to the zipcode -property of that address: +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.predicate.ts.rst -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.deep-dot-notation.js - :language: js +Supported Types +~~~~~~~~~~~~~~~ .. _rql-nil-type: Nil Type --------- +```````` -Realm Query Language include the ``nil`` type to represent a null pointer. +Realm Query Language includes the ``nil`` type to represent a null pointer. You can either reference ``nil`` directly in your queries or with a parameterized query. If you're using a parameterized query, each SDK maps its respective null pointer to ``nil``. -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.nil-type.js - :language: js - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.nil-type-parameterized-query.js - :language: js +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type.ts.rst .. _rql-operators: -.. _rql-comparison-operators: - -Comparison Operators --------------------- -The most straightforward operation in a search is to compare -values. +Operators +--------- -.. important:: Types Must Match - - The type on both sides of the operator must be equivalent. For - example, comparing an ObjectId with string will result in a precondition - failure with a message like: +.. _rql-comparison-operators: - .. code-block:: - :copyable: false +Comparison Operators +~~~~~~~~~~~~~~~~~~~~ - "Expected object of type object id for property 'id' on object of type - 'User', but received: 11223344556677889900aabb (Invalid value)" +Use comparison operators to compare values of matching data types. - You can compare any numeric type with any other numeric type, - including decimal, float, and Decimal128. +.. TODO: link or mention how ANY works (noted as equivalent to IN in this table) .. list-table:: :header-rows: 1 @@ -319,7 +154,7 @@ values. * - Operator - Description - * - ``BETWEEN {number1, number2}`` + * - ``BETWEEN {N1, N2}`` - Evaluates to ``true`` if the left-hand numerical or date expression is between or equal to the right-hand range. For dates, this evaluates to ``true`` if the left-hand date is within the right-hand date range. @@ -361,28 +196,32 @@ values. - Evaluates to ``true`` if the left-hand expression is not equal to the right-hand expression. -.. example:: - The following example uses Realm Query Language's comparison operators to: +The following example uses comparison operators to find to-do items whose +property values match certain criteria: - - Find high priority to-do items by comparing the value of the ``priority`` - property value with a threshold number, above which priority can be considered high. - - Find long-running to-do items by seeing if the ``progressMinutes`` property - is at or above a certain value. - - Find unassigned to-do items by finding items where the ``assignee`` property - is equal to ``null``. - - Find to-do items within a certain time range by finding items where the - ``progressMinutes`` property is between two numbers. - - Find to-do items with a certain amount of ``progressMinutes`` from the - given list. +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.comparison-operators.ts.rst + +.. important:: Types Must Match + + The type on both sides of the operator must be equivalent. For + example, comparing an ObjectId with string will result in a precondition + failure with a message like: + + .. code-block:: + :copyable: false + + "Expected object of type object id for property 'id' on object of type + 'User', but received: 11223344556677889900aabb (Invalid value)" + + You can compare any numeric type with any other numeric type, + including decimal, float, and Decimal128. - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.comparison-operators.js - :language: javascript .. _rql-logical-operators: Logical Operators ------------------ +~~~~~~~~~~~~~~~~~ Make compound predicates using logical operators. @@ -405,145 +244,17 @@ Make compound predicates using logical operators. | ``||`` - Evaluates to ``true`` if either expression returns ``true``. -.. example:: - - We can use the query language's logical operators to find - all of Ali's completed to-do items. That is, we find all items - where the ``assignee`` property value is equal to 'Ali' AND - the ``isComplete`` property value is ``true``: - - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.logical-operators.js - :language: javascript - -.. _rql-string-operators: - -String Operators ----------------- - -Compare string values using these string operators. -Regex-like wildcards allow more flexibility in search. - -.. note:: - - You can use the following modifiers with the string operators: - - - ``[c]`` for case insensitivity. - - .. code-block:: javascript - - "name CONTAINS[c] $0", 'a' - -.. list-table:: - :header-rows: 1 - :widths: 40 60 - - * - Operator - - Description - - * - | ``BEGINSWITH`` - - Evaluates to ``true`` if the left-hand string expression begins with - the right-hand string expression. This is similar to ``contains``, - but only matches if the right-hand string expression is found - at the beginning of the left-hand string expression. - - * - | ``CONTAINS`` - - Evaluates to ``true`` if the right-hand string expression - is found anywhere in the left-hand string expression. - - * - | ``ENDSWITH`` - - Evaluates to ``true`` if the left-hand string expression ends - with the right-hand string expression. This is similar to ``contains``, - but only matches if the left-hand string expression is found - at the very end of the right-hand string expression. - - * - | ``LIKE`` - - Evaluates to ``true`` if the left-hand string expression - matches the right-hand string wildcard string - expression. A wildcard string expression is a string - that uses normal characters with two special wildcard - characters: - - - The ``*`` wildcard matches zero or more of any character - - The ``?`` wildcard matches any character. - - For example, the wildcard string "d?g" matches "dog", - "dig", and "dug", but not "ding", "dg", or "a dog". - - * - | ``==``, ``=`` - - Evaluates to ``true`` if the left-hand string is lexicographically equal - to the right-hand string. - - * - | ``!=``, ``<>`` - - Evaluates to ``true`` if the left-hand string is not lexicographically - equal to the right-hand string. - -.. example:: - - We use the query engine's string operators to find: - - - Projects with a name starting with the letter 'e' - - Projects with names that contain 'ie' +The following example uses logical operators to combine multiple predicates: - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.string-operators.js - :language: javascript - -.. _rql-objectid-uuid-operators: - -ObjectId and UUID Operators ---------------------------- - -Query :manual:`BSON ObjectIds ` and -:manual:`UUIDs `. -These data types are often used as primary keys. - -To query with ObjectIds, use a parameterized query. Pass the ObjectId or UUID -you're querying against as the argument. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.oid-literal.js - :language: js - -You can also put a string representation of the ObjectId you're evaluating -in ``oid()``. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.oid.js - :language: js - -To query with UUIDs, put a string representation of the UUID you're evaluating -in ``uuid()``. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.uuid.js - :language: js - -.. list-table:: - :header-rows: 1 - :widths: 40 60 - - * - Operator - - Description - - * - | ``==``, ``=`` - - Evaluates to ``true`` if the left-hand value is equal - to the right-hand value. - - * - | ``!=``, ``<>`` - - Evaluates to ``true`` if the left-hand value is not equal - to the right-hand value. +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.logical-operators.ts.rst .. _rql-arithmetic-operators: Arithmetic Operators --------------------- - -Perform basic arithmetic in one side of a RQL expression when evaluating -numeric data types. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.basic-arithmetic.js - :language: js - -You can also use multiple object properties together in a mathematic operation. +~~~~~~~~~~~~~~~~~~~~ -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.arithmetic-obj-properties.js - :language: js +Use arithmetic operators to perform basic arithmetic in an expression when +evaluating numeric data types, including object properties. .. list-table:: :header-rows: 1 @@ -563,112 +274,17 @@ You can also use multiple object properties together in a mathematic operation. * - | ``()`` - Group expressions together. -.. _rql-type-operator: +The following example uses arithmetic operators on Item object properties containing numeric values: -Type Operator -------------- - -Check the type of a property using the ``@type`` operator. -You can only use the type operator with mixed types and dictionaries. - -Evaluate the property against a string representation of the data type name. -Refer to SDK documentation on the mapping from the SDK language's data types -to Realm data types. - -.. list-table:: - :header-rows: 1 - :widths: 40 60 - - * - Operator - - Description - - * - ``@type`` - - Check if type of a property is the property name as a string. - Use ``==`` and ``!=`` to compare equality. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.type-operator.js - :language: js - -.. _rql-dictionary-operators: - -Dictionary Operators --------------------- - -Compare dictionary values using these dictionary operators. - -.. list-table:: - :header-rows: 1 - :widths: 40 60 - - * - Operator - - Description - - * - ``@values`` - - Returns objects that have the value specified in the right-hand expression. - - * - ``@keys`` - - Returns objects that have the key specified in the right-hand expression. - - * - ``@size``, ``@count`` - - The number of elements in a dictionary. - - * - ``Dictionary['key']`` - - Access the value at a key of a dictionary. - - * - ``ALL | ANY | NONE .@type`` - - Checks if the dictionary contains properties of certain type. - -You can also use dictionary operators in combination with -:ref:`comparison operators ` to filter objects -based on dictionary keys and values. The following examples show some ways -to use dictionary operators with comparison operators. All examples query -a collection of Realm objects with a dictionary property named ``dict``. - -.. example:: - - The following examples use various dictionary operators. - - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.dictionary-operators.js - :language: js - -.. _rql-date-operators: - -Date Operators --------------- - -Query date types in a realm. - -Generally, you should use a parameterized query to pass a date data type -from the SDK language you are using to a query. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.date-parameterized-query.js - :language: js - -You can also specify dates in the following two ways: - -- As a specific date (in UTC)- ``YYYY-MM-DD@HH:mm:ss:nnnnnnnnnn`` (year-month-day@hours:minutes:seconds:nanoseconds), UTC. - You can also use ``T`` instead of ``@`` to separate the date from the time. -- As a time in seconds since the :wikipedia:`Unix epoch `- ``Ts:n``, where ``T`` designates the start of the time, - ``s`` is the number of seconds, and ``n`` is the number of nanoseconds. - -Date supports :ref:`comparison operators `. - -.. example:: - - The following example shows how to use a parameterized query with - a date object: - - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.date-alt-representation.js - :language: js +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.basic-arithmetic.ts.rst .. _rql-aggregate-operators: Aggregate Operators -------------------- +~~~~~~~~~~~~~~~~~~~ -Apply an aggregate operator to a collection property of a Realm -object. Aggregate operators traverse a collection and reduce it to a -single value. +Aggregate operators traverse a collection and reduce it to a single value. +You can use aggregate operators on collection properties, such as a list, or on .. list-table:: :header-rows: 1 @@ -697,334 +313,42 @@ single value. - Evaluates to the sum of a given numerical property across a collection, excluding ``null`` values. -.. example:: - - These examples all query for projects containing to-do items that meet - this criteria: - - - Projects with average item priority above 5. - - Projects with an item whose priority is less than 5. - - Projects with an item whose priority is greater than 5. - - Projects with more than 5 items. - - Projects with long-running items. - - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.aggregate-operators.js - :language: javascript - -.. _rql-collection-operators: - -Collection Operators --------------------- - -A **collection operator** lets you query list properties within a collection of objects. -Collection operators filter a collection by applying a predicate -to every element of a given list property of the object. -If the predicate returns true, the object is included in the output collection. - -.. list-table:: - :header-rows: 1 - :widths: 30 70 - - * - Operator - - Description - - * - ``ALL`` - - Returns objects where the predicate evaluates to ``true`` for all objects - in the collection. - - * - ``ANY``, ``SOME`` - - Returns objects where the predicate evaluates to ``true`` for any objects - in the collection. - - * - ``NONE`` - - Returns objects where the predicate evaluates to false for all objects - in the collection. - -.. example:: - - This example uses collection operators to find projects that contain to-do items - matching certain criteria: - - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.set-operators.js - :language: js - -.. _rql-list-queries: - -List Comparisons ----------------- - -You can use :ref:`comparison operators ` and -:ref:`collection operators ` to filter based -on lists of data. - -You can compare any type of valid list. This includes: - -- collections of Realm objects, which let you filter against other data - in the realm. - - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.list-comparisons-collection.js - :language: js - -- lists defined directly in the query, which let you filter against - static data. You define static lists as a comma-separated list of - literal values enclosed in opening (``{``) and closing (``}``) braces. - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.list-comparisons-static.js - :language: js +The following example uses aggregate operators to find project whose ``items`` +collection property meets certain criteria: -- native list objects passed in a :ref:`parameterized expression - `, which let you pass application data - directly to your queries. +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.aggregate-operators.ts.rst - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.list-comparisons-parameterized.js - :language: js - -If you do not define a collection operator, a list expression defaults -to the ``ANY`` operator. - -.. example:: - - These two list queries are equivalent: - - - ``age == ANY {18, 21}`` - - ``age == {18, 21}`` - - Both of these queries return objects with an age property equal to - either 18 or 21. You could also do the opposite by returning objects - only if the age is not equal to either 18 or 21: - - - ``age == NONE {18, 21}`` - -The following table includes examples that illustrate how collection -operators interact with lists and comparison operators: - -.. list-table:: - :widths: 45 10 45 - - * - Expression - - Match? - - Reason - - * - ``ANY {1, 2, 3} > ALL {1, 2}`` - - true - - A value on the left (3) is greater than some value on the right (both 1 and 2) - - * - ``ANY {1, 2, 3} == NONE {1, 2}`` - - true - - 3 does not match either of 1 or 2 - - * - ``ANY {4, 8} == ANY {5, 9, 11}`` - - false - - Neither 4 nor 8 matches any value on the right (5, 9 or 11) - - * - ``ANY {1, 2, 7} <= NONE {1, 2}`` - - true - - A value on the left (7) is not less than or equal to both 1 and 2 - - * - ``ALL {1, 2} IN ANY {1, 2, 3}`` - - true - - Every value on the left (1 and 2) is equal to 1, 2 or 3 - - * - ``ALL {3, 1, 4, 3} == NONE {1, 2}`` - - false - - 1 matches a value in the NONE list (1 or 2) - - * - ``ALL {} in ALL {1, 2}`` - - true - - An empty list matches all lists - - * - ``NONE {1, 2, 3, 12} > ALL {5, 9, 11}`` - - false - - 12 is bigger than all values on the right (5, 9, and 11) - - * - ``NONE {4, 8} > ALL {5, 9, 11}`` - - true - - 4 and 8 are both less than some value on the right (5, 9, or 11) - - * - ``NONE {0, 1} < NONE {1, 2}`` - - true - - 0 and 1 are both less than none of 1 and 2 - -.. _rql-fts: - -Full Text Search ----------------- - -You can use RQL to query on properties that have a full-text search (FTS) -annotation. FTS supports boolean match word searches, rather than searches for relevance. -For information on enabling FTS on a property, refer to :ref:`sdks-fts-property`. - -To query these properties, use the ``TEXT`` predicate in your query. - -You can search for entire words or phrases, or limit your results with the following characters: - -- Exclude results for a word by placing the ``-`` character in front of the word. -- Specify prefixes by placing the ``*`` character at the end of a prefix. Suffix - searching is not currently supported. - -In the following example, we query the ``Item.name`` property: - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.test.snippet.rql-fts.js - :language: js - -Full-Text Search Tokenizer Details -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Full-Text Search (FTS) indexes support: - -- Tokens are diacritics- and case-insensitive. -- Tokens can only consist of characters from ASCII and the Latin-1 supplement (western languages). - All other characters are considered whitespace. -- Words split by a hyphen (-) are split into two tokens. For example, ``full-text`` - splits into ``full`` and ``text``. - -.. _rql-geospatial: - -Geospatial Queries ------------------- - -You can query against geospatial data using the ``geoWithin`` operator. -The ``geoWithin`` operator takes the latitude/longitude pair in a custom -embedded object's ``coordinates`` property and a geospatial shape. The -operator checks whether the ``cordinates`` point is contained within the -geospatial shape. - -The following geospatial shapes are supported for querying: - -- ``GeoCircle`` -- ``GeoBox`` -- ``GeoPolygon`` - -To query geospatial data: - -1. Create an object with a property containing the embedded geospatial data. -2. Define the geospatial shape to set the boundary for the query. -3. Query using the ``geoWithin`` RQL operator. - -In the following query, we are checking that the coordinates of the embeddeded -``location`` property are contained within the ``GeoCircle`` shape, ``smallCircle``: - -.. literalinclude:: /examples/generated/node/v12/geospatial.test.snippet.rql-geospatial.js - :language: js - -For more information on defining geospatial shapes and objects with embedded -geospatial data, refer to :ref:`sdks-define-geospatial-object`. - -.. _rql-backlinks: - -Backlink Queries ----------------- - -A backlink is an inverse relationship link that lets you look up objects -that reference another object. Backlinks use the to-one and to-many -relationships defined in your object schemas but reverse the direction. -Every relationship that you define in your schema implicitly has a -corresponding backlink. - -You can access backlinks in queries using the -``@links..`` syntax, where ```` -and ```` refer to a specific property on an object type -that references the queried object type. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.backlinks-atLinks.js - :language: js - -You can also define a ``linkingObjects`` property to explicitly include -the backlink in your data model. This lets you reference the backlink -through an assigned property name using standard :ref:`dot notation -`. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.backlinks-linkingObjects.js - :language: js - -The result of a backlink is treated like a collection and supports -:ref:`collection operators `. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.backlinks-collection-operators.js - :language: js - -You can use :ref:`aggregate operators ` on the backlink collection. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.backlinks-aggregate-operators.js - :language: js - -You can query the count of all relationships that point to an object by -using the ``@count`` operator directly on ``@links``. - -.. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.backlinks-atCount.js - :language: js - -.. _rql-subqueries: - -Subqueries ----------- - -Iterate through list properties with another query using the -``SUBQUERY()`` predicate function. - -Subqueries are useful for the following scenarios: - -- Matching each object in a list property on multiple conditions -- Counting the number of objects that match a subquery - - -``SUBQUERY()`` has the following structure: - -.. code-block:: js - - SUBQUERY(, , ) - -- ``collection``: The name of the property to iterate through -- ``variableName``: A variable name of the element to use in the subquery -- ``predicate``: The subquery predicate. - Use the variable specified by ``variableName`` to refer to the - currently-iterated element. - -A subquery iterates through the given collection and checks the given predicate -against each object in the collection. The predicate can refer to the current -iterated object with the variable name passed to ``SUBQUERY()``. - -A subquery expression resolves to a list of objects. -Realm only supports the ``@count`` aggregate operator on the result -of a subquery. This allows you to count how many objects in the subquery -input collection matched the predicate. - -You can use the count of the subquery result as you would any other number -in a valid expression. In particular, you can compare the count with the -number ``0`` to return all matching objects. +.. _rql-sort-distinct-limit: +Sort and Limit Operators +~~~~~~~~~~~~~~~~~~~~~~~~ -.. example:: +Use sort and limit operators to shape your query results collection. You can +combine these operators across multiple properties. - The following example shows two subquery filters on a collection of projects. + For example, if you ``SORT (priority DESC, name DESC)``, the query + returns sorted by priority, and then by name when priority + value is the same. - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.subquery.js - :language: js -.. _rql-sort-distinct-limit: -Sort, Distinct & Limit ----------------------- Sort and limit the results collection of your query using additional operators. .. list-table:: :header-rows: 1 - :widths: 40 60 + :widths: 20 80 * - Operator - Description - * - ``SORT`` + * - ``SORT`` (``ASC`` or ``DESC``) - Specify the name of the property to compare, and whether to sort by - ascending (``ASC``) or descending (``DESC``) order. If you specify + ascending (``ASC``) or descending (``DESC``) order. If you specify multiple SORT fields, you must specify sort order for each field. - With multiple sort fields, the query sorts by the first field, and - then the second. - - For example, if you ``SORT (priority DESC, name DESC)``, the query - returns sorted by priority, and then by name when priority - value is the same. + With multiple sort fields, the query sorts by the first field, and + then the second. * - ``DISTINCT`` - Specify a name of the property to compare. Remove duplicates @@ -1046,12 +370,30 @@ Sort and limit the results collection of your query using additional operators. - Enforcing uniqueness by name - Limiting the results to 5 items - .. literalinclude:: /examples/generated/realm-query-language/realm-query-language.snippet.sort-distinct-limit.js + .. literalinclude:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit.js :language: javascript -.. _flexible-sync-rql-limitations: +.. important:: Order Matters + + Queries are executed in order. This includes the order of the operators in + the query *and* the order of properties within an operator, if applicable. + This can greatly impact the results returned. For example, sorting a query before + limiting it can return very different results than sorting *after* limiting + it. + + .. .. include:: /includes/file.rst + :start-after: text to start after (Optional} + :end-before: text to end before (Optional} + + For example, + + - ``LIMIT(5) SORT(priority DESC)`` returns + the top 5 items in the entire collection, which are then sorted by priority. However, ``SORT(priority DESC) LIMIT(5)`` + + +Data Type Queries +----------------- + + -Flexible Sync RQL Limitations ------------------------------ -.. include:: /includes/flex-sync-limitations.rst