diff --git a/source/includes/api-details/cpp/crud/read-filter-or-query-objects-description.rst b/source/includes/api-details/cpp/crud/read-filter-or-query-objects-description.rst new file mode 100644 index 0000000000..2d98d1bcd9 --- /dev/null +++ b/source/includes/api-details/cpp/crud/read-filter-or-query-objects-description.rst @@ -0,0 +1,11 @@ +To filter data, call the ``.where()`` function on a collection with a valid +query. Currently, C++ supports only a subset of RQL operators. + +Supported Query Operators +````````````````````````` + +C++ supports the following query operators: + +- Equality (``==``, ``!=``) +- Greater than/less than (``>``, ``>=``, ``<``, ``<=``) +- Compound queries (``||``, ``&&``) diff --git a/source/includes/api-details/csharp/crud/read-filter-or-query-objects-description.rst b/source/includes/api-details/csharp/crud/read-filter-or-query-objects-description.rst new file mode 100644 index 0000000000..96d0eea24c --- /dev/null +++ b/source/includes/api-details/csharp/crud/read-filter-or-query-objects-description.rst @@ -0,0 +1,38 @@ +To query, filter, and sort data in the database, use the SDK query engine. +There are two ways to use the query engine with C#: + +- :ref:`LINQ Syntax ` +- :ref:`Realm Query Language (RQL) ` + +Use LINQ syntax for querying when possible, as it provides compile-time checks +for queries and aligns with .NET conventions. + +Filter Data with LINQ +````````````````````` + +To filter data with LINQ syntax, call the :dotnet-sdk:`Where() +` operator with a +:dotnet-sdk:`Predicate ` that describes +the subset of data you want to access. + +.. literalinclude:: /examples/generated/dotnet/QueryEngineExamples.snippet.logical.cs + :language: csharp + +Filter Data with RQL +```````````````````` + +You can also use the :ref:`Realm Query Language ` (RQL) +to query realms. RQL is a string-based query language used to access the query +engine. When using RQL, you use the +:dotnet-sdk:`Filter() ` +method: + +.. literalinclude:: /examples/generated/dotnet/QueryEngineExamples.snippet.rql.cs + :language: csharp + +.. important:: + + Because :ref:`LINQ ` provides compile-time error checking + of queries, you should use it instead of RQL in most cases. If you require + features beyond LINQ's current capabilities, such as using + :ref:`aggregation `, use RQL. diff --git a/source/includes/api-details/dart/crud/read-filter-or-query-objects-description.rst b/source/includes/api-details/dart/crud/read-filter-or-query-objects-description.rst new file mode 100644 index 0000000000..49206471ae --- /dev/null +++ b/source/includes/api-details/dart/crud/read-filter-or-query-objects-description.rst @@ -0,0 +1,8 @@ +Filter a collection to retrieve a specific segment of objects with the +:flutter-sdk:`Realm.query() ` method. In the +``query()`` method's argument, use RQL to perform filtering. + +.. literalinclude:: /examples/generated/flutter/read_write_data_test.snippet.filter.dart + :language: dart + +You can use iterable arguments in your filter. diff --git a/source/includes/api-details/java/crud/read-filter-or-query-objects-java-description.rst b/source/includes/api-details/java/crud/read-filter-or-query-objects-java-description.rst new file mode 100644 index 0000000000..31c53ef925 --- /dev/null +++ b/source/includes/api-details/java/crud/read-filter-or-query-objects-java-description.rst @@ -0,0 +1,32 @@ +In Java, you can filter objects with either the Fluent interface or RQL. + +Filter Data with Fluent Interface +````````````````````````````````` + +To filter data with the Fluent interface, filter data with a +:java-sdk:`RealmQuery `. For more details, refer +to :ref:`Fluent interface `. + +In the following example, we use the Fluent interface comparison operators to: + +- Find high priority tasks by comparing the value of the ``priority`` property value with a threshold number, above which priority can be considered high. +- Find just-started or short-running tasks by seeing if the ``progressMinutes`` property falls within a certain range. +- Find unassigned tasks by finding tasks where the ``assignee`` property is equal to null. +- Find tasks assigned to specific teammates Ali or Jamie by seeing if the ``assignee`` property is in a list of names. + +.. literalinclude:: /examples/generated/java/sync/ReadsTest.snippet.filter-results.java + :language: java + :copyable: false + +Filter Data with RQL +```````````````````` + +To filter data with RQL, use :java-sdk:`RealmQuery.rawPredicate() +`. +For more information about syntax, usage and limitations, +refer to the :ref:`Realm Query Language reference `. + +RQL can use either the class and property names defined in your SDK model +classes or the internal names defined with ``@RealmField``. You can combine +raw predicates with other raw predicates or type-safe predicates created with +``RealmQuery``. diff --git a/source/includes/api-details/java/crud/read-filter-or-query-objects-kotlin-description.rst b/source/includes/api-details/java/crud/read-filter-or-query-objects-kotlin-description.rst new file mode 100644 index 0000000000..f20e572e94 --- /dev/null +++ b/source/includes/api-details/java/crud/read-filter-or-query-objects-kotlin-description.rst @@ -0,0 +1,33 @@ +In Java or Kotlin (Java SDK), you can filter objects with either the +Fluent interface or RQL. + +Filter Data with Fluent Interface +````````````````````````````````` + +To filter data with the Fluent interface, filter data with a +:java-sdk:`RealmQuery `. For more details, refer +to :ref:`Fluent interface `. + +In the following example, we use the Fluent interface comparison operators to: + +- Find high priority tasks by comparing the value of the ``priority`` property value with a threshold number, above which priority can be considered high. +- Find just-started or short-running tasks by seeing if the ``progressMinutes`` property falls within a certain range. +- Find unassigned tasks by finding tasks where the ``assignee`` property is equal to null. +- Find tasks assigned to specific teammates Ali or Jamie by seeing if the ``assignee`` property is in a list of names. + +.. literalinclude:: /examples/generated/java/sync/ReadsTest.snippet.filter-results.kt + :language: kotlin + :copyable: false + +Filter Data with RQL +```````````````````` + +To filter data with RQL, use :java-sdk:`RealmQuery.rawPredicate() +`. +For more information about syntax, usage and limitations, +refer to the :ref:`Realm Query Language reference `. + +RQL can use either the class and property names defined in your SDK model +classes or the internal names defined with ``@RealmField``. You can combine +raw predicates with other raw predicates or type-safe predicates created with +``RealmQuery``. diff --git a/source/includes/api-details/javascript/crud/read-filter-or-query-objects-js-ts-description.rst b/source/includes/api-details/javascript/crud/read-filter-or-query-objects-js-ts-description.rst new file mode 100644 index 0000000000..ac5faa0d24 --- /dev/null +++ b/source/includes/api-details/javascript/crud/read-filter-or-query-objects-js-ts-description.rst @@ -0,0 +1,10 @@ +To filter a query, call :js-sdk:`filtered() +` on the query results collection. +Pass a Realm Query Language query as argument to ``filtered()``. + +In the following example, we use RQL comparison operators to: + +- Find high priority tasks by comparing the value of the ``priority`` property + value with a threshold number, above which priority can be considered high. +- Find just-started or short-running tasks by seeing if the ``progressMinutes`` + property falls within a certain range. diff --git a/source/includes/api-details/kotlin/crud/read-filter-or-query-objects-description.rst b/source/includes/api-details/kotlin/crud/read-filter-or-query-objects-description.rst new file mode 100644 index 0000000000..224a25408a --- /dev/null +++ b/source/includes/api-details/kotlin/crud/read-filter-or-query-objects-description.rst @@ -0,0 +1,6 @@ +To filter by property, you can pass Realm Query Language (RQL) filters and +operators, use Kotlin's built-in extension methods or the SDK's convenience +methods, or use a combination. + +In the following example, we query a ``Frog`` object type and filter by the +``name`` property. diff --git a/source/includes/api-details/objectivec/crud/read-filter-or-query-objects-description.rst b/source/includes/api-details/objectivec/crud/read-filter-or-query-objects-description.rst new file mode 100644 index 0000000000..7cbab7d32c --- /dev/null +++ b/source/includes/api-details/objectivec/crud/read-filter-or-query-objects-description.rst @@ -0,0 +1,6 @@ +To filter results in Objective-C, call :objc-sdk:`-[RLMResults objectsWhere:] +` +with a query predicate. + +For more details about the supported operators available for Objective-C +queries, refer to :ref:`sdks-nspredicate-query`. diff --git a/source/includes/api-details/swift/crud/read-filter-or-query-objects-description.rst b/source/includes/api-details/swift/crud/read-filter-or-query-objects-description.rst new file mode 100644 index 0000000000..4c2394b038 --- /dev/null +++ b/source/includes/api-details/swift/crud/read-filter-or-query-objects-description.rst @@ -0,0 +1,29 @@ +Swift has its own query APIs that use either the type-safe ``where`` syntax, +or a string ``NSPredicate`` query. For more details about the supported +operators available for Swift queries, refer to :ref:`sdks-filter-data-swift`. + +Type-Safe Queries +````````````````` + +To use the :ref:`Realm Swift Query API `, call +:swift-sdk:`.where ` with a closure that contains a query +expression as an argument. + +This query API provides compile-time type-safe query checking. Prefer using +this API over the older string-based ``NSPredicate`` API. + +.. literalinclude:: /examples/generated/code/start/ReadRealmObjects.snippet.where.swift + :language: swift + +NSPredicate Queries +``````````````````` + +To filter with the older string-based ``NSPredicate`` API, call +:swift-sdk:`Results.filter(_:) +` +with a query predicate. + +Prefer using the type-safe query API unless you are using an SDK version +older than 10.19.0. The string-based ``NSPredicate`` query API does not provide +compile-time checking for valid query syntax, and may crash at runtime with +an invalid ``NSPredicate``. diff --git a/source/includes/sdk-examples/crud/read-filter-or-query-objects.rst b/source/includes/sdk-examples/crud/read-filter-or-query-objects.rst new file mode 100644 index 0000000000..7b3e62bb55 --- /dev/null +++ b/source/includes/sdk-examples/crud/read-filter-or-query-objects.rst @@ -0,0 +1,63 @@ +.. tabs-drivers:: + + tabs: + - id: cpp-sdk + content: | + + .. literalinclude:: /examples/generated/cpp/crud.snippet.filter-using-type-safe-query.cpp + :language: cpp + + - id: csharp + content: | + + .. literalinclude:: /examples/generated/dotnet/QueryEngineExamples.snippet.rql.cs + :language: csharp + + - id: dart + content: | + + .. literalinclude:: /examples/generated/flutter/read_write_data_test.snippet.filter-iterable.dart + :language: dart + + - id: java + content: | + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.realm-query-language.java + :language: java + + - id: java-kotlin + content: | + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.realm-query-language.kt + :language: kotlin + + - id: javascript + content: | + + .. literalinclude:: /examples/generated/node/read-and-write-data.snippet.read-and-write-filter-queries.js + :language: javascript + + - id: kotlin + content: | + + .. literalinclude:: /examples/generated/kotlin/ReadTest.snippet.query-by-property.kt + :language: kotlin + + - id: objectivec + content: | + + .. literalinclude:: /examples/generated/code/start/ReadWriteData.snippet.filter.m + :language: objectivec + + - id: swift + content: | + + .. literalinclude:: /examples/generated/code/start/ReadRealmObjects.snippet.filter.swift + :language: swift + + - id: typescript + content: | + + .. literalinclude:: /examples/MissingPlaceholders/example.ts + :language: typescript + :copyable: false diff --git a/source/sdk/crud/query-engines.txt b/source/sdk/crud/query-engines.txt index 4339163c25..647a4a1dbd 100644 --- a/source/sdk/crud/query-engines.txt +++ b/source/sdk/crud/query-engines.txt @@ -15,5 +15,5 @@ query engines: - :ref:`realm-query-language` - :ref:`java-filter-data` -- :ref:`dotnet-linq` +- :ref:`sdks-dotnet-linq` - :ref:`sdks-filter-data-swift` diff --git a/source/sdk/crud/query-engines/filter-data-java-sdk.txt b/source/sdk/crud/query-engines/filter-data-java-sdk.txt index 12a2f46f34..f1a6bcf158 100644 --- a/source/sdk/crud/query-engines/filter-data-java-sdk.txt +++ b/source/sdk/crud/query-engines/filter-data-java-sdk.txt @@ -1,13 +1,603 @@ -.. _java-filter-data: +.. _sdks-java-filter-data: ====================== Filter Data - Java SDK ====================== +.. meta:: + :description: Provide a short description of the consolidated page. This is critical for SEO. + :keywords: Realm, Java SDK, code example + +.. facet:: + :name: genre + :values: reference + +.. facet:: + :name: programming_language + :values: java, kotlin + .. contents:: On this page :local: :backlinks: none :depth: 2 :class: singlecol -Placeholder for filtering data in the Java SDK using the Fluent interface. \ No newline at end of file +.. tabs-selector:: drivers + +Atlas Device SDK for Java uses a :wikipedia:`Fluent interface ` +to construct multi-clause queries that are passed to the query engine. + +See :java-sdk:`RealmQuery API ` for a complete list +of available methods. + +There are several types of operators available to filter an SDK collection. +Filters work by **evaluating** an operator expression for every object in the +collection being filtered. If the expression resolves to ``true``, the SDK +includes the object in the results collection. + +An **expression** consists of one of the following: + +- The name of a property of the object currently being evaluated. +- An operator and up to two argument expression(s). +- A literal string, number, or date. + +Fluent Interface Expressions +---------------------------- + +About the Examples In This Section +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The examples in this section use a simple data set for a +task list app. The two SDK object types are ``Project`` +and ``Task``. A ``Task`` has a name, assignee's name, and +completed flag. There is also an arbitrary number for +priority (higher is more important) and a count of +minutes spent working on it. A ``Project`` has zero or more +``Tasks``. + +See the schema for these two classes, ``Project`` and +``Task``, below: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/sync/ProjectTask.snippet.projecttask.java + :language: java + :caption: ProjectTask.java + :copyable: false + + .. literalinclude:: /examples/generated/java/sync/Project.snippet.project.java + :language: java + :caption: Project.java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/sync/ProjectTask.snippet.projecttask.kt + :language: kotlin + :caption: ProjectTask.kt + :copyable: false + + .. literalinclude:: /examples/generated/java/sync/Project.snippet.project.kt + :language: kotlin + :caption: Project.kt + :copyable: false + +Comparison Operators +~~~~~~~~~~~~~~~~~~~~ + +The most straightforward operation in a search is to compare +values. + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Operator + - Description + + * - ``between`` + - 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. + + * - | ``equalTo`` + - Evaluates to ``true`` if the left-hand expression is equal to the right-hand expression. + + * - | ``greaterThan`` + - Evaluates to ``true`` if the left-hand numerical or date expression is greater than the right-hand numerical or date expression. For dates, this evaluates to ``true`` if the left-hand date is later than the right-hand date. + + * - | ``greaterThanOrEqualTo`` + - Evaluates to ``true`` if the left-hand numerical or date expression is greater than or equal to the right-hand numerical or date expression. For dates, this evaluates to ``true`` if the left-hand date is later than or the same as the right-hand date. + + * - ``in`` + - Evaluates to ``true`` if the left-hand expression is in the right-hand list. + + * - | ``lessThan`` + - Evaluates to ``true`` if the left-hand numerical or date expression is less than the right-hand numerical or date expression. For dates, this evaluates to ``true`` if the left-hand date is earlier than the right-hand date. + + * - | ``lessThanOrEqualTo`` + - Evaluates to ``true`` if the left-hand numeric expression is less than or equal to the right-hand numeric expression. For dates, this evaluates to ``true`` if the left-hand date is earlier than or the same as the right-hand date. + + * - | ``notEqualTo`` + - Evaluates to ``true`` if the left-hand expression is not equal to the right-hand expression. + +.. example:: + + The following example uses the query engine's + comparison operators to: + + - Find high priority tasks by comparing the value of the ``priority`` property value with a threshold number, above which priority can be considered high. + - Find just-started or short-running tasks by seeing if the ``progressMinutes`` property falls within a certain range. + - Find unassigned tasks by finding tasks where the ``assignee`` property is equal to ``null``. + - Find tasks assigned to specific teammates Ali or Jamie by seeing if the ``assignee`` property is in a list of names. + + .. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.comparison-operators.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.comparison-operators.kt + :language: kotlin + :copyable: false + +Logical Operators +~~~~~~~~~~~~~~~~~ + +You can make compound predicates using logical operators. + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Operator + - Description + + * - | ``and`` + - Evaluates to ``true`` if both left-hand and right-hand expressions are ``true``. + + * - | ``not`` + - Negates the result of the given expression. + + * - | ``or`` + - 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 tasks. That is, we find all tasks + where the ``assignee`` property value is equal to 'Ali' AND + the ``isComplete`` property value is ``true``: + + .. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.logical-operators.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.logical-operators.kt + :language: kotlin + :copyable: false + +.. _java-string-operators: + +String Operators +~~~~~~~~~~~~~~~~ + +You can compare string values using these string operators. +Regex-like wildcards allow more flexibility in search. + +.. 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 left-hand string expression is found at the beginning of the right-hand string expression. + + * - ``contains`` + - Evaluates to ``true`` if the left-hand string expression is found anywhere in the right-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". + + * - | ``equalTo`` + - Evaluates to ``true`` if the left-hand string is 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' and + projects with names that contain 'ie': + + .. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.string-operators.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.string-operators.kt + :language: kotlin + :copyable: false + +.. note:: Case-insensitive Character Limitations + + Case-insensitive string operators only support the + ``Latin Basic``, ``Latin Supplement``, ``Latin Extended A``, and + ``Latin Extended B (UTF-8 range 0–591)`` character sets. Setting + the case insensitive flag in queries when using ``equalTo``, + ``notEqualTo``, ``contains``, ``endsWith``, ``beginsWith``, or + ``like`` only works on English locale characters. + +Aggregate Operators +~~~~~~~~~~~~~~~~~~~ + +You can apply an aggregate operator to a collection property of an SDK object. +Aggregate operators traverse a collection and reduce it to a single value. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Operator + - Description + + * - | ``average`` + - Evaluates to the average value of a given numerical property across a collection. + + * - | ``count`` + - Evaluates to the number of objects in the given collection. + + * - | ``max`` + - Evaluates to the highest value of a given numerical property across a collection. + + * - | ``min`` + - Evaluates to the lowest value of a given numerical property across a collection. + + * - | ``sum`` + - Evaluates to the sum of a given numerical property across a collection. + +.. example:: + + We create a couple of filters to show different facets of + the data: + + - Projects with average tasks priority above 5. + - Long running projects. + + .. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.aggregate-operators.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/sync/QueryEngineTest.snippet.aggregate-operators.kt + :language: kotlin + :copyable: false + +Filter, Sort, Limit, Unique, and Chain Queries +---------------------------------------------- + +About the Examples in This Section +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The examples in this section use two Realm object types: ``Teacher`` +and ``Student``. + +See the schema for these two classes below: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/Teacher.snippet.complete.java + :language: java + :caption: Teacher.java + :copyable: false + + .. literalinclude:: /examples/generated/java/local/Student.snippet.complete.java + :language: java + :caption: Student.java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/TeacherKt.snippet.complete.kt + :language: kotlin + :caption: Teacher.kt + :copyable: false + + .. literalinclude:: /examples/generated/java/local/StudentKt.snippet.complete.kt + :language: kotlin + :caption: Student.kt + :copyable: false + +.. _java-client-filters: + +Filters +~~~~~~~ + +You can build filters using the operator methods of the +:wikipedia:`fluent interface ` exposed by the +:java-sdk:`RealmQuery ` class: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.filters.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.filters.kt + :language: kotlin + :copyable: false + +This gives you a new instance of the class :java-sdk:`RealmResults `, +containing teachers with the name "Ms. Langtree" or "Mrs. Jacobs". + +``RealmQuery`` includes several methods that can execute queries: + +- :java-sdk:`findAll() ` blocks until + it finds all objects that meet the query conditions + +- :java-sdk:`findAllAsync() ` + returns immediately and finds all objects that meet the query + conditions asynchronously on a background thread + +- :java-sdk:`findFirst() ` blocks + until it finds the first object that meets the query conditions + +- :java-sdk:`findFirstAsync() ` + returns immediately and finds the first object that meets the query + conditions asynchronously on a background thread + +Queries return a list of references to the matching SDK objects using the +:java-sdk:`RealmResults ` type. + +.. _java-link-queries: + +Link Queries +````````````` + +When referring to an object property, you can use **dot notation** to refer +to child properties of that object. You can refer to the properties of +:ref:`embedded objects ` and :ref:`relationships +` with dot notation. + +For example, consider a query for all teachers with a student named +"Wirt" or "Greg": + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.link-queries.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.link-queries.kt + :language: kotlin + :copyable: false + +You can even use dot notation to query inverse relationships: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.link-queries-inverse.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.link-queries-inverse.kt + :language: kotlin + :copyable: false + +.. _java-sort-results: + +Sort Results +~~~~~~~~~~~~ + +.. important:: + + Realm applies the ``distinct()``, ``sort()`` and + ``limit()`` methods in the order you specify. Depending on the + data set this can alter the query result. Generally, you should + apply ``limit()`` last to avoid unintended result sets. + +You can define the order of query results using the +:java-sdk:`sort() ` +method: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.sort.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.sort.kt + :language: kotlin + :copyable: false + +Sorts organize results in ascending order by default. To organize results +in descending order, pass ``Sort.DESCENDING`` as a second argument. +You can resolve sort order ties between identical property values +by passing an array of properties instead of a single property: in the +event of a tie, the SDK sorts the tied objects by subsequent +properties in order. + +.. note:: String Sorting Limitations + + The SDK uses non-standard sorting for upper and lowercase + letters, sorting them together rather than sorting uppercase first. + As a result, ``'- !"#0&()*,./:;?_+<=>123aAbBcC...xXyYzZ`` is the + actual sorting order in Realm. Additionally, sorting + strings only supports the ``Latin Basic``, ``Latin Supplement``, + ``Latin Extended A``, and ``Latin Extended B (UTF-8 range 0–591)`` + character sets. + +.. _java-limit-results: + +Limit Results +~~~~~~~~~~~~~ + +You can cap the number of query results to a specific maximum number +using the :java-sdk:`limit() ` +method: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.limit.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.limit.kt + :language: kotlin + :copyable: false + +Limited result collections automatically update like any other query +result. Consequently, objects might drop out of the collection as +underlying data changes. + +.. tip:: Pagination is Not Necessary for SDK Optimization + + Some databases encourage paginating results with limits to avoid + reading unnecessary data from disk or using too much memory. + + Since Atlas Device SDK queries are lazy, there is no need to + take such measures. The SDK only loads objects from query + results when they are explicitly accessed. + +.. tip:: Deleted Notifications in Limited Results + + :ref:`Collection notifications ` + report objects as deleted when they drop out of the result set. + This does not necessarily mean that they have been deleted from the + underlying database, just that they are no longer part of the + query result. + +.. _java-unique-results: + +Unique Results +~~~~~~~~~~~~~~ + +You can reduce query results to unique values for a given field or fields +using the :java-sdk:`distinct() +` method: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.unique.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.unique.kt + :language: kotlin + :copyable: false + +You can only call ``distinct()`` on integer, long, short, and ``String`` +fields; other field types will throw an exception. As with sorting, +you can specify multiple fields to resolve ties. + +.. _java-chain-queries: + +Chain Queries +~~~~~~~~~~~~~ + +You can apply additional filters to a results collection by calling the +:java-sdk:`where() ` method: + +.. tabs-drivers:: + + .. tab:: + :tabid: java + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.chain-queries.java + :language: java + :copyable: false + + .. tab:: + :tabid: java-kotlin + + .. literalinclude:: /examples/generated/java/local/FilterDataTest.snippet.chain-queries.kt + :language: kotlin + :copyable: false + +The ``where()`` method returns a ``RealmQuery`` that you can resolve into +a ``RealmResults`` using a ``find`` method. Filtered results can only +return objects of the same type as the original results set, but are +otherwise able to use any :ref:`filters `. diff --git a/source/sdk/crud/query-engines/filter-data-linq.txt b/source/sdk/crud/query-engines/filter-data-linq.txt index 508b0ed878..1c7a47c6d6 100644 --- a/source/sdk/crud/query-engines/filter-data-linq.txt +++ b/source/sdk/crud/query-engines/filter-data-linq.txt @@ -1,8 +1,4 @@ -.. _dotnet-filter-data: -.. _dotnet-filter-queries-based-on-object-properties: -.. _dotnet-filter-results: -.. _dotnet-client-query-engine: -.. _dotnet-linq: +.. _sdks-dotnet-linq: =========================== Filter and Sort Data - LINQ @@ -14,4 +10,242 @@ Filter and Sort Data - LINQ :depth: 2 :class: singlecol -Placeholder page for querying data in .NET SDK using LINQ. +The Atlas Device SDK query engine implements standard `LINQ +`__ +syntax. + +There are several operators available to filter an SDK collection with LINQ. +Filters work by evaluating an operator expression for every object in the +collection being filtered. If the expression resolves to ``true``, the SDK +includes the object in the results collection. + +An expression consists of one of the following: + +- The name of a property of the object currently being evaluated +- An operator +- A value of any type used by the SDK (string, date, number, boolean, etc.) + +.. note:: + + The SDK does not currently support all of the LINQ operators. Refer to the + :ref:`sdks-dotnet-unsupported-linq` section on this page for a list of + those unsupported operators. + +Comparison Operators +~~~~~~~~~~~~~~~~~~~~ + +Value comparisons + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Operator + - Description + + * - | ``==`` + - Evaluates to ``true`` if the left-hand expression is equal to the + right-hand expression. + + * - | ``>`` + - Evaluates to ``true`` if the left-hand numerical or date expression is + greater than the right-hand numerical or date expression. For dates, this + evaluates to ``true`` if the left-hand date is later than the right-hand + date. + + * - | ``>=`` + - Evaluates to ``true`` if the left-hand numerical or date expression is + greater than or equal to the right-hand numerical or date expression. For + dates, this evaluates to ``true`` if the left-hand date is later than or + the same as the right-hand date. + + * - | ``<`` + - Evaluates to ``true`` if the left-hand numerical or date expression is + less than the right-hand numerical or date expression. For dates, this + evaluates to ``true`` if the left-hand date is earlier than the + right-hand date. + + * - | ``<=`` + - Evaluates to ``true`` if the left-hand numeric expression is less than + or equal to the right-hand numeric expression. For dates, this evaluates + to ``true`` if the left-hand date is earlier than or the same as the + right-hand date. + + * - | ``!=`` + - Evaluates to ``true`` if the left-hand expression is not equal to the + right-hand expression. + +.. example:: + + The following example uses the query engine's + comparison operators to: + + - Find high priority tasks by comparing the value of the ``priority`` property + value with a threshold number, above which priority can be considered high. + - Find just-started or short-running tasks by seeing if the ``progressMinutes`` + property falls within a certain range. + - Find unassigned tasks by finding tasks where the ``assignee`` property is + equal to ``null``. + - Find tasks assigned to specific teammates Ali or Jamie by seeing if the + ``assignee`` property is in a list of names. + + .. literalinclude:: /examples/generated/dotnet/QueryEngineExamples.snippet.comparisons.cs + :language: csharp + +Logical Operators +~~~~~~~~~~~~~~~~~ + +You can use the logical operators listed in the following table to make compound +predicates: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Operator + - Description + + * - | ``&&`` + - Evaluates to ``true`` if both left-hand and right-hand expressions are + ``true``. + + * - | ``!`` + - Negates the result of the given expression. + + * - | ``||`` + - 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 tasks. That is, we find all tasks + where the ``assignee`` property value is equal to 'Ali' AND + the ``isComplete`` property value is ``true``: + + .. literalinclude:: /examples/generated/dotnet/QueryEngineExamples.snippet.logical.cs + :language: csharp + +String Operators +~~~~~~~~~~~~~~~~ + +You can compare string values using the string operators listed in the following +table. Regex-like wildcards allow more flexibility in search. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Operator + - Description + + * - ``StartsWith`` + - 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 left-hand string expression is found at the beginning of + the right-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". + + * - | ``Equals`` + - Evaluates to ``true`` if the left-hand string is + `lexicographically `_ + equal to the right-hand string. + + * - | ``Contains`` + - Evaluates to ``true`` if the left-hand string expression is found anywhere + in the right-hand string expression. + + * - | ``string.IsNullOrEmpty`` + - Evaluates to ``true`` if the left-hand string expression is null or empty. + Note that ``IsNullOrEmpty()`` is a static method on ``string``. + +.. example:: + + The following examples use the query engine's string operators to find + tasks: + + .. literalinclude:: /examples/generated/dotnet/QueryEngineExamples.snippet.strings.cs + :language: csharp + +.. important:: Case Comparisons + + When evaluating strings, the second parameter in all functions *except* ``Like`` + must be either ``StringComparison.OrdinalIgnoreCase`` or + ``StringComparison.Ordinal``. For the ``Like()`` method, the second + parameter is a boolean value (where "true" means "case sensitive"). + +.. _dotnet-linq-fts: + +Full Text Search +~~~~~~~~~~~~~~~~ + +You can use LINQ to query on properties that have :ref:`enabled Full-Text Search +` (FTS). To query these properties, use +:dotnet-sdk:`QueryMethods.FullTextSearch +`. +The following examples query the ``Person.Biography`` field: + +.. literalinclude:: /examples/generated/dotnet/Indexing.snippet.linq-query-fts.cs + :language: csharp + +.. _sdks-dotnet-unsupported-linq: + +Unsupported LINQ Operators +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following LINQ operators are not currently supported by the SDK: + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Category + - Unsupported Operators + + * - | Concatenation + - - ``Concat`` + - ``Join``. While ``Join`` is not supported, it is not needed with + the SDK. Instead of using keys in a Join statement, as you would in + a traditional relational database, you can reference another type + as a property. For more information, refer to :ref:`sdks-relationships`. + - ``GroupJoin`` + + * - | Grouping + - - ``GroupBy`` + + * - | Partitioning + - - ``Take`` + - ``Skip`` + - ``TakeWhile`` + - ``SkipWhile`` + + * - | Projection + - - ``SelectMany`` + - ``Select``, with one exception: when used with the query syntax, ``Select`` + is supported as long as you select the Realm object itself and not a + derivative: + + ``var tasks = from t in realm.All() where t.Assignee == "Caleb" select t;`` + + * - | Sets + - - ``Distinct`` + - ``Union`` + - ``Intersect`` + - ``Except`` diff --git a/source/sdk/crud/read.txt b/source/sdk/crud/read.txt index 5d9219b7b4..793e0e5e69 100644 --- a/source/sdk/crud/read.txt +++ b/source/sdk/crud/read.txt @@ -355,6 +355,90 @@ querying for all objects of a type. Filter or Query Objects ~~~~~~~~~~~~~~~~~~~~~~~ +A **filter** selects a subset of results based on the value(s) of one or more +object properties. The most common use case is to find objects where a certain +property matches a certain value. Additionally, you can compare strings, +aggregate over collections of numbers, and use logical operators to build up +complex queries. + +The SDK provides several full-featured query engines you +can use to define filters. The core query engine uses :ref:`Realm Query +Language (RQL) ` to construct queries. RQL is a +string-based query language that you can use to retrieve objects from the +database. Some of the SDK languages provide special query APIs that provide +idiomatic query syntax and features. The available query APIs include: + +- :ref:`RQL `: C++, C#, Dart, Java, JavaScript, Kotlin, + TypeScript +- :ref:`LINQ `: C# +- :ref:`Type-Safe and NSPredicate Queries `: Swift, + Objective-C +- :ref:`Fluent Interface `: Java, Kotlin (Java SDK) + +For more details about the supported operators when using each of these query +APIs, refer to the query engine for your preferred language. + +.. tabs-drivers:: + + .. tab:: + :tabid: cpp-sdk + + .. include:: /includes/api-details/cpp/crud/read-filter-or-query-objects-description.rst + + .. tab:: + :tabid: csharp + + .. include:: /includes/api-details/csharp/crud/read-filter-or-query-objects-description.rst + + .. tab:: + :tabid: dart + + .. include:: /includes/api-details/dart/crud/read-filter-or-query-objects-description.rst + + .. tab:: + :tabid: java + + .. include:: /includes/api-details/java/crud/read-filter-or-query-objects-java-description.rst + + .. tab:: + :tabid: java-kotlin + + .. include:: /includes/api-details/java/crud/read-filter-or-query-objects-kotlin-description.rst + + .. tab:: + :tabid: javascript + + .. include:: /includes/api-details/javascript/crud/read-filter-or-query-objects-js-ts-description.rst + + .. tab:: + :tabid: kotlin + + .. include:: /includes/api-details/kotlin/crud/read-filter-or-query-objects-description.rst + + .. tab:: + :tabid: objectivec + + .. include:: /includes/api-details/objectivec/crud/read-filter-or-query-objects-description.rst + + .. tab:: + :tabid: swift + + .. include:: /includes/api-details/swift/crud/read-filter-or-query-objects-description.rst + + .. tab:: + :tabid: typescript + + .. include:: /includes/api-details/javascript/crud/read-filter-or-query-objects-js-ts-description.rst + +.. include:: /includes/sdk-examples/crud/read-filter-or-query-objects.rst + +.. tip:: Filter on Related and Embedded Object Properties + + To filter a query based on a property of an :ref:`embedded object + ` or a :ref:`related object + `, use dot-notation as if it were in a regular, + nested object. + .. _sdks-read-find-object-by-primary-key: Find an Object by Primary Key