From c86e8695bd1ef9fde395ac7099b32c9c93a54644 Mon Sep 17 00:00:00 2001 From: cbullinger Date: Thu, 30 May 2024 12:48:56 -0400 Subject: [PATCH] Rearranged page order and updated example snippet formatting --- .../__tests__/realm-query-language.test.ts | 262 ++++--- ...ippet.backlinks-aggregate-operators.ts.rst | 9 - ...uage.test.snippet.backlinks-atLinks.ts.rst | 4 +- ...ppet.backlinks-collection-operators.ts.rst | 27 +- ...st.snippet.backlinks-linkingObjects.ts.rst | 1 + ...guage.test.snippet.basic-arithmetic.ts.rst | 9 +- ...e.test.snippet.comparison-operators.ts.rst | 3 - ...st.snippet.date-parameterized-query.ts.rst | 3 +- ...uage.test.snippet.deep-dot-notation.ts.rst | 2 + ...e.test.snippet.dictionary-operators.ts.rst | 30 +- ...-language.test.snippet.dot-notation.ts.rst | 5 + ...ippet.equivalent-lists-any-operator.ts.rst | 7 + ...snippet.list-comparisons-collection.ts.rst | 2 + ...ppet.list-comparisons-parameterized.ts.rst | 2 + ...est.snippet.list-comparisons-static.ts.rst | 2 + ...uery-language.test.snippet.nil-type.ts.rst | 5 +- ...y-language.test.snippet.oid-literal.ts.rst | 3 - ...alm-query-language.test.snippet.oid.ts.rst | 17 +- ...query-language.test.snippet.rql-fts.ts.rst | 4 +- ...language.test.snippet.set-operators.ts.rst | 7 +- ...t.sort-distinct-limit-order-matters.ts.rst | 12 + ...ge.test.snippet.sort-distinct-limit.ts.rst | 11 +- ...guage.test.snippet.string-operators.ts.rst | 20 +- ...anguage.test.snippet.subquery-count.ts.rst | 5 - ...uery-language.test.snippet.subquery.ts.rst | 8 +- ...language.test.snippet.type-operator.ts.rst | 12 +- ...lm-query-language.test.snippet.uuid.ts.rst | 3 - ...data-models.snippet.rql-data-models.ts.rst | 2 + .../query-engines/realm-query-language.txt | 728 +++++++++++++----- 29 files changed, 845 insertions(+), 360 deletions(-) delete mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-aggregate-operators.ts.rst create mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dot-notation.ts.rst create mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.equivalent-lists-any-operator.ts.rst delete mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid-literal.ts.rst create mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit-order-matters.ts.rst delete mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery-count.ts.rst delete mode 100644 source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.uuid.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 673075c14b..d8d0bca06d 100644 --- a/examples/node/v12/__tests__/realm-query-language.test.ts +++ b/examples/node/v12/__tests__/realm-query-language.test.ts @@ -16,7 +16,7 @@ describe("Realm Query Language Reference", () => { name: "Main Branch", address: { name: "Main Branch", - street: "123 Main St", + street: "999 Big Boulevard", zipcode: 10019, }, }; @@ -65,7 +65,7 @@ describe("Realm Query Language Reference", () => { quota: 1, // doesn't meet quota comments: { status: "Behind schedule", projectNumber: "70150" }, projectLocation: mainBranch, - // Mixed property is of type dictionary of mixed values + // Mixed property is of type dictionary of mixed values // (date, list of strings, bool, and int) additionalInfo: { startDate: new Date("2021-01-01"), @@ -131,7 +131,7 @@ describe("Realm Query Language Reference", () => { quota: 11, // doesn't meet quota comments: { status: "On track", projectNumber: "N/A" }, projectLocation: austinBranch, - // Mixed property is of type list, containing string and nested + // Mixed property is of type list, containing string and nested // dictionary of mixed values (date, boolean, and int) additionalInfo: [ "Customer is difficult to work with.", @@ -336,9 +336,9 @@ describe("Realm Query Language Reference", () => { const projects = realm.objects(Project); const startWithE = projects.filtered( // :snippet-start: string-operators - // Find projects whose name starts with the letter 'e' + // Find projects whose name starts with 'E' or 'e' // (case-insensitive). - "name BEGINSWITH[c] $0", "e" + "name BEGINSWITH[c] $0", "E" // :remove-start: ); expect(startWithE.length).toBe(1); @@ -346,13 +346,39 @@ describe("Realm Query Language Reference", () => { const containIe = projects.filtered( // :remove-end: - // Find projects whose name contains the letters 'ie' + // Find projects whose name contains 'ie' // (case-sensitive). "name CONTAINS $0", "ie" - // :snippet-end: + // :remove-start: ); expect(containIe.length).toBe(0); }); + + test("String comparisons", () => { + const projects = realm.objects(Project); + const items = realm.objects(Item); + // prettier-ignore + const assigneeBetween = items.filtered( + // :remove-end: + + // Find items where the assignee name is lexicographically + // between 'Ali' and 'Chris' (case-sensitive). + "assignee BETWEEN { $0 , $1 }", "Ali", "Chris" + // :remove-start: + ); + // prettier-ignore + const compareStreet = projects.filtered( + // :remove-end: + + // Find projects where the street address is lexicographically + // greater than '123 Main St' (case-sensitive). + "projectLocation.address.street > $0", "123 Main St" + // :snippet-end: + ); + + expect(compareStreet.length).toBe(2); + expect(assigneeBetween.length).toBe(2); + }); }); // prettier-ignore @@ -407,8 +433,8 @@ describe("Realm Query Language Reference", () => { expect(longRunningProjects.length).toBe(1); }); - describe("Collection queries", () => { - test("Collection operators", () => { + describe("Collection operators", () => { + test("Collection queries", () => { const projects = realm.objects(Project); // prettier-ignore const noCompleteItems = projects.filtered( @@ -421,8 +447,8 @@ describe("Realm Query Language Reference", () => { const anyTopPriorityItems = projects.filtered( // :remove-end: - // Find projects that contain an item with priority 10. - "ANY items.priority == $0", 10 + // Find projects that contain any item with priority 10. + "items.priority == $0", 10 // (ANY operator is implied.) // :remove-start: ); // prettier-ignore @@ -446,7 +472,8 @@ describe("Realm Query Language Reference", () => { const notAssignedToAlexOrAli = projects.filtered( // :remove-end: - // Projects with no items assigned to either Alex or Ali. + // Find projects with no items assigned to either + // Alex or Ali. "NONE items.assignee IN { $0 , $1 }", "Alex", "Ali" // :snippet-end: ); @@ -464,11 +491,15 @@ describe("Realm Query Language Reference", () => { const collectionQuery = projects.filtered( // :snippet-start: list-comparisons-collection + // Find an item with the specified ObjectId value + // in the `items` collection. "oid(631a072f75120729dc9223d9) IN items._id" // :snippet-end: ); const staticQuery = items.filtered( // :snippet-start: list-comparisons-static + // Find items with a priority value matching + // any value in the static list. "priority IN {0, 1, 2}" // :snippet-end: ); @@ -478,9 +509,33 @@ describe("Realm Query Language Reference", () => { new BSON.ObjectId("631a0737c98f89f5b81cd24d"), new BSON.ObjectId("631a073c833a34ade21db2b2"), ]; + // Find items with an ObjectId value matching any value in the + // parameterized list. const parameterizedQuery = realm.objects(Item).filtered("_id IN $0", ids); // :snippet-end: + // prettier-ignore + const anyOperator = items.filtered( + // :snippet-start: equivalent-lists-any-operator + "assignee == ANY { $0, $1 }", "Alex", "Ali" + // :remove-start: + ); + // prettier-ignore + const equivalentAnyOperator = items.filtered( + // :remove-end: + + "assignee == { $0, $1 }", "Alex", "Ali" // Equivalent (ANY is implied.) + // :remove-start: + ); + const equivalentNoneOperator = items.filtered( + // :remove-end: + + "assignee NONE { 'Alex', 'Ali' }" // Equivalent to != ANY. + // :snippet-end: + ); + + expect(anyOperator.length).toBe(2); + expect(equivalentAnyOperator.length).toBe(2); expect(collectionQuery.length).toBe(1); expect(staticQuery.length).toBe(1); expect(parameterizedQuery.length).toBe(3); @@ -535,94 +590,79 @@ describe("Realm Query Language Reference", () => { ); }); - test("Subquery queries", () => { - const projects = realm.objects(Project); - const subquery = projects.filtered( - // :snippet-start: subquery - // Find projects with incomplete to-do items assigned to Alex. - "SUBQUERY(items, $item, $item.isComplete == false AND $item.assignee == 'Alex').@count > 0" - // :snippet-end: - ); - expect(subquery.length).toBe(1); - expect(subquery[0].name).toBe("Example Project with Items"); - - const subquery2 = projects.filtered( - // :snippet-start: subquery-count - // Find projects where the number of completed to-do items - // is greater than or equal to the project's `quota` property. - "SUBQUERY(items, $item, $item.isComplete == true).@count >= quota" - // :snippet-end: - ); - - expect(subquery2.length).toBe(1); - expect(subquery2[0].name).toBe("Project that Meets Quota"); - }); + test("Subquery query", () => { + const projects = realm.objects("Project"); + const subquery = projects.filtered( + // :snippet-start: subquery + // Find projects with incomplete items with 'Demo' in the name. + "SUBQUERY(items, $item, $item.isComplete == false AND $item.name CONTAINS[c] 'Demo').@count > 0" + // :remove-start: + ); + expect(subquery.length).toBe(1); + expect(subquery[0].name).toBe("Project that Meets Quota"); + + const subquery2 = projects.filtered( + // :remove-end: + + // Find projects where the number of completed items + // is greater than or equal to the project's `quota` property. + "SUBQUERY(items, $item, $item.isComplete == true).@count >= quota" + // :snippet-end: + ); + + expect(subquery2.length).toBe(1); + expect(subquery2[0].name).toBe("Project that Meets Quota"); + }); // prettier-ignore test("Dictionary operators", () => { const dictionaries = realm.objects(Project); const statusKey = dictionaries.filtered( // :snippet-start: dictionary-operators - // Find `comments` dictionary properties with key 'status'. + // Find projects whose `comments` dictionary property + // have a key of 'status'. "comments.@keys == $0", "status" // :remove-start: ); const statusOnTrack = dictionaries.filtered( // :remove-end: - // Find `comments` dictionary properties with key 'status' - // and value 'On track'. - "comments['status'] == $0", "On track" + // Find projects whose `comments` dictionary property + // have a 'status' key with a value that ends in 'track'. + "comments['status'] LIKE $0", "*track" + // :remove-start: ); const numItemsInDict = dictionaries.filtered( // :remove-end: - // Find `comments` dictionary properties with - // more than one key-value pair. + // Find projects whose `comments` dictionary property + // have more than one key-value pair. "comments.@count > $0", 1 // :remove-start: ); - const hasString = dictionaries.filtered( - // :remove-end: - // Find `comments` dictionary properties where ANY - // values are of type 'string`. - "ANY comments.@type == 'string'" - // :remove-start: - ); - - const hasStringImplied = dictionaries.filtered( + const allString = dictionaries.filtered( // :remove-end: - "comments.@type == 'string'" // (Equivalent - ANY is implied.) - - // :remove-start: - ); - - const allInt = dictionaries.filtered( - // :remove-end: - // Find `comments` dictionary properties where ALL - // values are of type 'int'. - "ALL comments.@type == 'int'" + // Find projects whose `comments` dictionary property + // contains only values of type 'string'. + "ALL comments.@type == 'string'" // :remove-start: ); const noInts = dictionaries.filtered( // :remove-end: - // Find `comments` dictionary properties where NO - // values are of type 'int'. + // Find projects whose `comments` dictionary property + // contains no values of type 'int'. "NONE comments.@type == 'int'" - // :snippet-end: ); expect(statusKey.length).toBe(3); expect(statusOnTrack.length).toBe(1); expect(numItemsInDict.length).toBe(3); - expect(hasString.length).toBe(3); - expect(hasStringImplied.length).toBe(3); - expect(allInt.length).toBe(0); + expect(allString.length).toBe(3); expect(noInts.length).toBe(3); }); }); @@ -631,8 +671,8 @@ describe("Realm Query Language Reference", () => { test("Backlinks query @links", () => { const atLinksResult = realm.objects(Item).filtered( // :snippet-start: backlinks-atLinks - // Find items that belong to a project with a quota - // less than 10 (using '@links'). + // Find items that belong to a project with a quota less than 10 + // (using '@links..'). "@links.Project.items.quota < 10" // :snippet-end: ); @@ -641,6 +681,7 @@ describe("Realm Query Language Reference", () => { const linkingObjectsResult = realm.objects(Item).filtered( // :snippet-start: backlinks-linkingObjects // Find items that belong to a project with a quota greater than 10 + // through the Item object's `projects` property // (using 'LinkingObjects'). "projects.quota > 10" // :snippet-end: @@ -651,27 +692,30 @@ describe("Realm Query Language Reference", () => { test("Backlinks collection operators", () => { const anyResult = realm.objects(Item).filtered( // :snippet-start: backlinks-collection-operators - // Find items where ANY project that references the item + // Find items where no project that references the item // has a quota greater than 10. - "ANY @links.Project.items.quota > 10" + "NONE @links.Project.items.quota > 10" // :remove-start: ); - expect(anyResult.length).toBe(2); + expect(anyResult.length).toBe(5); const allResult = realm.objects(Item).filtered( // :remove-end: - // Find items where ALL projects that reference the item + + // Find items where all projects that reference the item // have a quota less than 5. "ALL @links.Project.items.quota < 5" - // :snippet-end: + // :remove-start: + ); expect(allResult.length).toBe(5); }); test("Backlinks aggregate operators", () => { const shallowResultLinkingObjects = realm.objects(Item).filtered( - // :snippet-start: backlinks-aggregate-operators - // Find items that are referenced by multiple projects + // :remove-end: + + // Find items that are referenced by multiple projects. "projects.@count > 1" // :remove-start: ); @@ -680,7 +724,8 @@ describe("Realm Query Language Reference", () => { const shallowResultAtLinks = realm.objects(Item).filtered( // :remove-end: - // Find items that are not referenced by any project + + // Find items that are not referenced by any project. "@links.Project.items.@count == 0" // :remove-start: ); @@ -689,10 +734,11 @@ describe("Realm Query Language Reference", () => { const deepResultAtLinks = realm.objects(Item).filtered( // :remove-end: + // Find items that belong to a project where the average item has - // been worked on for at least 5 minutes + // been worked on for at least 10 minutes "@links.Project.items.items.@avg.progressMinutes > 10" - // :snippet-end: + // :remove-start: ); expect(deepResultAtLinks.length).toBe(2); expect(deepResultAtLinks[0].name).toBe("Write tests"); @@ -700,8 +746,10 @@ describe("Realm Query Language Reference", () => { test("Count all backlinks (@links.@count)", () => { const result = realm.objects(Item).filtered( - // :snippet-start: backlinks-atCount - // Find items that are not referenced by another object of any type + // :remove-end: + + // Find items that are not referenced by another + // object of any type (backlink count is 0). "@links.@count == 0" // :snippet-end: ); @@ -722,7 +770,8 @@ describe("Realm Query Language Reference", () => { ); const mixedCollection = projects.filtered( // :remove-end: - // Find projects with an `additionalInfo` property of + + // Find projects with an `additionalInfo` property of // `collection` type, which matches list or dictionary types. "additionalInfo.@type == 'collection'" // :remove-start: @@ -730,14 +779,13 @@ describe("Realm Query Language Reference", () => { const mixedBool = projects.filtered( // :remove-end: - // Find projects with an `additionalInfo` property of + // Find projects with an `additionalInfo` property of // list type, where any list element is of type 'bool'. "additionalInfo[*].@type == 'bool'" // :snippet-end: ); - console.debug(mixedString[1].name + " and " + mixedBool[0].name); - // expect(mixedString.length).toBe(1); - // expect(mixedBool.length).toBe(1); + expect(mixedString.length).toBe(1); + expect(mixedBool.length).toBe(1); }); }); @@ -774,14 +822,14 @@ describe("Realm Query Language Reference", () => { const oidValueString = "6001c033600510df3bbfd864"; const uuid1String = "d1b186e1-e9e0-4768-a1a7-c492519d47ee"; const oidValue = new BSON.ObjectId(oidValueString); - const uuid1 = new BSON.UUID(uuid1String); + const uuidValue = new BSON.UUID(uuid1String); // Add, then delete objects for this test beforeEach(async () => { realm = await Realm.open({ schema: [OidUuid], path }); const obj1 = { _id: oidValue, - id: uuid1, + id: uuidValue, }; const obj2 = { _id: new BSON.ObjectId(), @@ -798,28 +846,47 @@ describe("Realm Query Language Reference", () => { Realm.deleteFile({ path }); }); - test("ObjectId Operator", () => { + test("ObjectId query", () => { const oidUuids = realm.objects("OidUuid"); + // prettier-ignore const oidStringLiteral = oidUuids.filtered( // :snippet-start: oid + // Find an item whose `_id` matches the ObjectID + // value passed to 'oid()'. "_id == oid(6001c033600510df3bbfd864)" - // :snippet-end: + // :remove-start: ); - // prettier-ignore + const oidInterpolation = oidUuids.filtered( - // :snippet-start:oid-literal + // :remove-end: + + // Find an item whose `_id` matches the ObjectID + // passed as a parameterized query argument. "_id == $0", oidValue - // :snippet-end: + // :remove-start: ); expect(oidStringLiteral.length).toBe(1); expect(oidInterpolation.length).toBe(1); }); - test("UUID Operator", () => { + test("UUID query", () => { const oidUuids = realm.objects("OidUuid"); const uuid = oidUuids.filtered( - // :snippet-start: uuid + // :remove-end: + + // Find an item whose `id` matches the UUID value + // passed to 'uuid()'. "id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)" + + // :remove-start: + ); + // prettier-ignore + const test = oidUuids.filtered( + // :remove-end: + + // Find an item whose `_id` matches the UUID + // passed as a parameterized query argument. + "id == $0", uuidValue // :snippet-end: ); expect(uuid.length).toBe(1); @@ -876,13 +943,14 @@ describe("Realm Query Language Reference", () => { // :snippet-start: date-parameterized-query // Find to-do items completed before today's date. "dateCompleted < $0", today - // :remove-start: ); const dateAlt1 = dates.filtered( // :remove-end: - // Find to-do items completed this year until today. + + // Find to-do items completed between the start of the year + // until today. "dateCompleted > $0 AND dateCompleted < $1", thisYear, today // :snippet-end: ); @@ -915,8 +983,8 @@ describe("Realm Query Language Reference", () => { const itemsStartingWithWri = items.filtered( // :remove-end: - // Use '*' to match any suffix characters: - // Find items starting with 'wri-'. + // Use '*' to match any characters after a prefix: + // Find items with a name that starts with 'wri'. "name TEXT $0", "wri*" // :snippet-end: ); diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-aggregate-operators.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-aggregate-operators.ts.rst deleted file mode 100644 index 3388676d86..0000000000 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-aggregate-operators.ts.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. code-block:: typescript - - // Find items that are referenced by multiple projects - "projects.@count > 1" - // Find items that are not referenced by any project - "@links.Project.items.@count == 0" - // Find items that belong to a project where the average item has - // been worked on for at least 5 minutes - "@links.Project.items.items.@avg.progressMinutes > 10" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-atLinks.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-atLinks.ts.rst index 8346571665..e877dfd1f9 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-atLinks.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-atLinks.ts.rst @@ -1,5 +1,5 @@ .. code-block:: typescript - // Find items that belong to a project with a quota - // less than 10 (using '@links'). + // Find items that belong to a project with a quota less than 10 + // (using '@links..'). "@links.Project.items.quota < 10" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-collection-operators.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-collection-operators.ts.rst index be0e56a7f9..fa70358f91 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-collection-operators.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-collection-operators.ts.rst @@ -1,8 +1,23 @@ .. code-block:: typescript - // Find items where ANY project that references the item - // has a quota greater than 10. - "ANY @links.Project.items.quota > 10" - // Find items where ALL projects that reference the item - // have a quota less than 5. - "ALL @links.Project.items.quota < 5" + // Find items where no project that references the item + // has a quota greater than 10. + "NONE @links.Project.items.quota > 10" + + // Find items where all projects that reference the item + // have a quota less than 5. + "ALL @links.Project.items.quota < 5" + + // Find items that are referenced by multiple projects. + "projects.@count > 1" + + // Find items that are not referenced by any project. + "@links.Project.items.@count == 0" + + // Find items that belong to a project where the average item has + // been worked on for at least 10 minutes + "@links.Project.items.items.@avg.progressMinutes > 10" + + // Find items that are not referenced by another + // object of any type (backlink count is 0). + "@links.@count == 0" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-linkingObjects.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-linkingObjects.ts.rst index 7269485ca6..e1a9e51086 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-linkingObjects.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-linkingObjects.ts.rst @@ -1,5 +1,6 @@ .. code-block:: typescript // Find items that belong to a project with a quota greater than 10 + // through the Item object's `projects` property // (using 'LinkingObjects'). "projects.quota > 10" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.basic-arithmetic.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.basic-arithmetic.ts.rst index 5e23fdbb10..f58f72e118 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.basic-arithmetic.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.basic-arithmetic.ts.rst @@ -1,5 +1,8 @@ .. code-block:: typescript - // Find items with a `priority` greater than 3. - "2 * priority > 6" // `priority > 3` - "priority >= 2 * (2 - 1) + 2" // `priority >= 4` + // Evaluate against an item's `priority` property value: + "2 * priority > 6" // resolves to `priority > 3` + "priority >= 2 * (2 - 1) + 2" // resolves to `priority >= 4` + + // Evaluate against multiple object property values: + "progressMinutes * priority == 90" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.comparison-operators.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.comparison-operators.ts.rst index 34128a6378..25061aab11 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.comparison-operators.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.comparison-operators.ts.rst @@ -3,9 +3,6 @@ // Compare `priority` values against a threshold value. "priority > $0", 5 - // Compare `progressMinutes` values against a threshold value. - "progressMinutes > $0", 120 - // Compare `assignee` values to `null` value. "assignee == $0", null diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.date-parameterized-query.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.date-parameterized-query.ts.rst index fd06d334ce..f83e455b95 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.date-parameterized-query.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.date-parameterized-query.ts.rst @@ -3,5 +3,6 @@ // Find to-do items completed before today's date. "dateCompleted < $0", today - // Find to-do items completed this year until today. + // Find to-do items completed between the start of the year + // until today. "dateCompleted > $0 AND dateCompleted < $1", thisYear, today diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.deep-dot-notation.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.deep-dot-notation.ts.rst index db769f001a..6e20a8cfe1 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.deep-dot-notation.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.deep-dot-notation.ts.rst @@ -1,3 +1,5 @@ .. code-block:: typescript + // Find projects whose `projectLocation` property contains + // an embedded Address object with a specific zip code. "projectLocation.address.zipcode == 10019" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dictionary-operators.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dictionary-operators.ts.rst index 1f883a4627..8b2bed7db4 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dictionary-operators.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dictionary-operators.ts.rst @@ -1,25 +1,21 @@ .. code-block:: typescript - // Find `comments` dictionary properties with key 'status'. + // Find projects whose `comments` dictionary property + // have a key of 'status'. "comments.@keys == $0", "status" - // Find `comments` dictionary properties with key 'status' - // and value 'On track'. - "comments['status'] == $0", "On track" - // Find `comments` dictionary properties with - // more than one key-value pair. - "comments.@count > $0", 1 + // Find projects whose `comments` dictionary property + // have a 'status' key with a value that ends in 'track'. + "comments['status'] LIKE $0", "*track" - // Find `comments` dictionary properties where ANY - // values are of type 'string`. - "ANY comments.@type == 'string'" - "comments.@type == 'string'" // (Equivalent - ANY is implied.) + // Find projects whose `comments` dictionary property + // have more than one key-value pair. + "comments.@count > $0", 1 - // Find `comments` dictionary properties where ALL - // values are of type 'int'. - "ALL comments.@type == 'int'" + // Find projects whose `comments` dictionary property + // contains only values of type 'string'. + "ALL comments.@type == 'string'" - // Find `comments` dictionary properties where NO - // values are of type 'int'. + // Find projects whose `comments` dictionary property + // contains no values of type 'int'. "NONE comments.@type == 'int'" - diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dot-notation.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dot-notation.ts.rst new file mode 100644 index 0000000000..011a3715b4 --- /dev/null +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.dot-notation.ts.rst @@ -0,0 +1,5 @@ +.. code-block:: typescript + + // Find projects whose `items` list property contains + // an Item object with a specific name. + "items[0].name == 'Approve project plan'" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.equivalent-lists-any-operator.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.equivalent-lists-any-operator.ts.rst new file mode 100644 index 0000000000..f35fae515e --- /dev/null +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.equivalent-lists-any-operator.ts.rst @@ -0,0 +1,7 @@ +.. code-block:: typescript + + "assignee == ANY { $0, $1 }", "Alex", "Ali" + + "assignee == { $0, $1 }", "Alex", "Ali" // Equivalent (ANY is implied.) + + "assignee NONE { 'Alex', 'Ali' }" // Equivalent to != ANY. diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-collection.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-collection.ts.rst index 290b29341e..ab5fef1b83 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-collection.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-collection.ts.rst @@ -1,3 +1,5 @@ .. code-block:: typescript + // Find an item with the specified ObjectId value + // in the `items` collection. "oid(631a072f75120729dc9223d9) IN items._id" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-parameterized.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-parameterized.ts.rst index 0641020373..5a3fc8f1d4 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-parameterized.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-parameterized.ts.rst @@ -5,4 +5,6 @@ new BSON.ObjectId("631a0737c98f89f5b81cd24d"), new BSON.ObjectId("631a073c833a34ade21db2b2"), ]; + // Find items with an ObjectId value matching any value in the + // parameterized list. const parameterizedQuery = realm.objects(Item).filtered("_id IN $0", ids); diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-static.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-static.ts.rst index e79c902584..df932d00da 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-static.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-static.ts.rst @@ -1,3 +1,5 @@ .. code-block:: typescript + // Find items with a priority value matching + // any value in the static list. "priority IN {0, 1, 2}" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type.ts.rst index 38ea382f9b..91769b4891 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.nil-type.ts.rst @@ -1,3 +1,6 @@ .. code-block:: typescript - "assignee == nil" + "assignee == nil" + + // 'null' maps to the SDK language's null pointer + "assignee == $0", null diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid-literal.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid-literal.ts.rst deleted file mode 100644 index 1b7ee896b1..0000000000 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid-literal.ts.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. code-block:: typescript - - "_id == $0", oidValue diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid.ts.rst index a7909effbe..cb00dbe046 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid.ts.rst @@ -1,3 +1,18 @@ .. code-block:: typescript - "_id == oid(6001c033600510df3bbfd864)" + // Find an item whose `_id` matches the ObjectID + // value passed to 'oid()'. + "_id == oid(6001c033600510df3bbfd864)" + + // Find an item whose `_id` matches the ObjectID + // passed as a parameterized query argument. + "_id == $0", oidValue + + // Find an item whose `id` matches the UUID value + // passed to 'uuid()'. + "id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)" + + + // Find an item whose `_id` matches the UUID + // passed as a parameterized query argument. + "id == $0", uuidValue diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.rql-fts.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.rql-fts.ts.rst index b861e87002..ac69dc328e 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.rql-fts.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.rql-fts.ts.rst @@ -7,6 +7,6 @@ // Find items with 'write' but not 'tests' in the name. "name TEXT $0", "write -tests" - // Use '*' to match any suffix characters: - // Find items starting with 'wri-'. + // Use '*' to match any characters after a prefix: + // Find items with a name that starts with 'wri'. "name TEXT $0", "wri*" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.set-operators.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.set-operators.ts.rst index a2667eece5..92c1c2d89a 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.set-operators.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.set-operators.ts.rst @@ -3,8 +3,8 @@ // Find projects with no complete items. "NONE items.isComplete == $0", true - // Find projects that contain an item with priority 10. - "ANY items.priority == $0", 10 + // Find projects that contain any item with priority 10. + "items.priority == $0", 10 // (ANY operator is implied.) // Find projects that only contain completed items. "ALL items.isComplete == $0", true @@ -13,5 +13,6 @@ // either Alex or Ali. "ANY items.assignee IN { $0 , $1 }", "Alex", "Ali" - // Projects with no items assigned to either Alex or Ali. + // Find projects with no items assigned to either + // Alex or Ali. "NONE items.assignee IN { $0 , $1 }", "Alex", "Ali" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit-order-matters.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit-order-matters.ts.rst new file mode 100644 index 0000000000..200a1408d7 --- /dev/null +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit-order-matters.ts.rst @@ -0,0 +1,12 @@ +.. code-block:: typescript + + // 1. Sorts by highest priority. + // 2. Returns the first item. + // 3. Remove duplicate names (N/A because a single + // item is always considered distinct). + "assignee == null SORT(priority ASC) LIMIT(1) DISTINCT(name)" + + // 1. Removes any duplicates by name. + // 2. Sorts by highest priority. + // 3. Returns the first item. + "assignee == null DISTINCT(name) SORT(priority ASC) LIMIT(1)" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit.ts.rst index 7ee32e3146..b4580eadc9 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit.ts.rst @@ -1,3 +1,12 @@ .. code-block:: typescript - "assignee == 'Ali' SORT(priority DESC) DISTINCT(name) LIMIT(5)" + // Find incomplete items, sort by `priority` + // in descending order, then sort equal `priority` + // values by `progressMinutes` in ascending order. + "isComplete == false SORT(priority DESC, progressMinutes ASC)" + + // Find high priority items, then remove from the results + // any items with duplicate `name` AND `assignee` values. + "priority >= 5 DISTINCT(name, assignee)" + // Find in-progress items, then return the first 10 results. + "progressMinutes > 0 && isComplete != true LIMIT(10)" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.string-operators.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.string-operators.ts.rst index 8effdea009..e1254e7ed6 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.string-operators.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.string-operators.ts.rst @@ -1,9 +1,17 @@ .. code-block:: typescript - // Find projects whose name starts with the letter 'e' - // (case-insensitive). - "name BEGINSWITH[c] $0", "e" + // Find projects whose name starts with 'E' or 'e' + // (case-insensitive). + "name BEGINSWITH[c] $0", "E" - // Find projects whose name contains the letters 'ie' - // (case-sensitive). - "name CONTAINS $0", "ie" + // Find projects whose name contains 'ie' + // (case-sensitive). + "name CONTAINS $0", "ie" + + // Find items where the assignee name is lexicographically + // between 'Ali' and 'Chris' (case-sensitive). + "assignee BETWEEN { $0 , $1 }", "Ali", "Chris" + + // Find projects where the street address is lexicographically + // greater than '123 Main St' (case-sensitive). + "projectLocation.address.street > $0", "123 Main St" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery-count.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery-count.ts.rst deleted file mode 100644 index 51371a79fa..0000000000 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery-count.ts.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. code-block:: typescript - - // Find projects where the number of completed to-do items - // is greater than or equal to the project's `quota` property. - "SUBQUERY(items, $item, $item.isComplete == true).@count >= quota" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery.ts.rst index 9228876e1c..126129f7e2 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery.ts.rst @@ -1,4 +1,8 @@ .. code-block:: typescript - // Find projects with incomplete to-do items assigned to Alex. - "SUBQUERY(items, $item, $item.isComplete == false AND $item.assignee == 'Alex').@count > 0" + // Find projects with incomplete items with 'Demo' in the name. + "SUBQUERY(items, $item, $item.isComplete == false AND $item.name CONTAINS[c] 'Demo').@count > 0" + + // Find projects where the number of completed items + // is greater than or equal to the project's `quota` property. + "SUBQUERY(items, $item, $item.isComplete == true).@count >= quota" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.type-operator.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.type-operator.ts.rst index 90a837faa8..fc9ad3f4df 100644 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.type-operator.ts.rst +++ b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.type-operator.ts.rst @@ -1,5 +1,13 @@ .. code-block:: typescript - "mixedType.@type == 'string'" + // Find projects with an `additionalInfo` property of + // string type. + "additionalInfo.@type == 'string'" - "mixedType.@type == 'bool'" + // Find projects with an `additionalInfo` property of + // `collection` type, which matches list or dictionary types. + "additionalInfo.@type == 'collection'" + + // Find projects with an `additionalInfo` property of + // list type, where any list element is of type 'bool'. + "additionalInfo[*].@type == 'bool'" diff --git a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.uuid.ts.rst b/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.uuid.ts.rst deleted file mode 100644 index 1141952739..0000000000 --- a/source/examples/generated/node/v12/formatted/realm-query-language.test.snippet.uuid.ts.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. code-block:: typescript - - "id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)" diff --git a/source/examples/generated/node/v12/formatted/rql-data-models.snippet.rql-data-models.ts.rst b/source/examples/generated/node/v12/formatted/rql-data-models.snippet.rql-data-models.ts.rst index 57dfa8ba30..4c74ff4715 100644 --- a/source/examples/generated/node/v12/formatted/rql-data-models.snippet.rql-data-models.ts.rst +++ b/source/examples/generated/node/v12/formatted/rql-data-models.snippet.rql-data-models.ts.rst @@ -33,6 +33,7 @@ quota?: number; comments?: Realm.Dictionary; projectLocation?: Office; + additionalInfo!: Realm.Mixed; static schema: ObjectSchema = { name: "Project", @@ -43,6 +44,7 @@ quota: "int?", comments: "string?{}", projectLocation: "Office?", + additionalInfo: "mixed", }, primaryKey: "_id", }; diff --git a/source/sdk/crud/query-engines/realm-query-language.txt b/source/sdk/crud/query-engines/realm-query-language.txt index 6220062176..f443ff4f80 100644 --- a/source/sdk/crud/query-engines/realm-query-language.txt +++ b/source/sdk/crud/query-engines/realm-query-language.txt @@ -7,7 +7,7 @@ Realm Query Language (RQL) .. meta:: :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 + :keywords: Realm, Flutter SDK, Kotlin SDK, Java SDK, Node.js SDK, code example .. facet:: :name: genre @@ -25,48 +25,36 @@ Realm Query Language (RQL) .. 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. -Realm Query Language syntax is based on `NSPredicate -`__. - -Queries evaluate a predicate for every object in the collection being queried. -If the predicate resolves to ``true``, the results collection includes the object. +Realm Query Language (RQL) is a string-based query language that you can use +to construct queries in most Atlas Device SDKs. The SDK-specific methods pass +the queries +to the Realm database query engine, which retrieves matching database objects. -You can use Realm Query Language in most Realm SDKs with your SDK's filter -or query methods. The Swift SDK is the exception, as it uses the -:ref:`NSPredicate query API `. -Some SDKs also support idiomatic APIs for querying realms in their language. +.. important:: Swift SDK Does Not Support Realm Query Language (RQL) -Query with Realm SDKs ---------------------- + The Swift SDK does *not* support querying with Realm Query Language. + Instead, it uses NSPredicate to query a database. For more information, refer to :ref:`Type-Safe and NSPredicate Queries (Swift SDK) `. -For language and SDK-specific methods for querying data, refer to the related -documentation: +With the exception of the Swift SDK, you can use Realm Query Language with your preferred SDK's filter +or query methods. For more information, refer to :ref:`sdks-crud-read`. -- :ref:`sdks-crud-read` +The following SDKs also support language-specific idiomatic APIs for querying databases: - :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. - You can instead use NSPredicate to query Realm. For examples of querying - Realm in the Swift SDK, refer to :ref:`Filter Data - Swift SDK `. - You can also use Realm Query Language to browse for data in :ref:`Realm Studio `. Realm Studio is a visual tool -to view, edit, and design Realm files. +to view, edit, and design ``.realm`` database files. Examples on This Page --------------------- -Many of the examples in this page use a simple data set for a to-do list app. +Most of the examples on this page use a simple data set for a to-do list app +that include the following database objects: The two Realm object types are ``Project`` and ``Item``. -- An ``Item`` has a name, assignee's name, and completed flag. +- ``Item``: Each item object 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 ``Items`` and an optional quota @@ -80,8 +68,11 @@ See the schema for these two classes, ``Project`` and ``Item``, below: Query Syntax ------------ -Expressions and Predicates -~~~~~~~~~~~~~~~~~~~~~~~~~~ +Realm Query Language syntax is based on `NSPredicate +`__. + +Queries evaluate a predicate for every object in the collection being queried. +If the predicate resolves to ``true``, the results collection includes the object. Realm Query Language uses expressions and predicates to evaluate queries. @@ -91,21 +82,34 @@ Realm Query Language uses expressions and predicates to evaluate queries. - **Predicates** are expressions that evaluate to ``true`` or ``false``. For example, ``name == 'Ali'`` is a predicate that evaluates to ``true`` if the name property is 'Ali'. + Realm Query Language also supports the following predicates: -TRUEPREDICATE and FALSEPREDICATE + - ``TRUEPREDICATE`` - Matches all objects. This is the default predicate. + - ``FALSEPREDICATE`` - Matches no objects. -Case Sensitivity -~~~~~~~~~~~~~~~~ +.. _rql-parameterized-queries: -Unless otherwise noted, RQL operators and keywords are case insensitive. +Parameterized vs. Serialized Queries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can format queries in the following two ways: + +- **Serialized queries** pass values directly in the expression. + +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.serialized-query.ts.rst + +- **Parameterized queries** pass interpolated variables as additional + arguments. The syntax for interpolated variables is + ``$``, starting at ``0`` and incrementing for each additional variable. + +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.predicate.ts.rst + +Unless otherwise noted, both formats are supported. -``[c]`` denotes case sensitivity in the following examples. Dot & Bracket Notation ~~~~~~~~~~~~~~~~~~~~~~ -.. TODO: confirm how we want to communicate which SDK versions support bracket notation - You can use **dot notation** or **bracket notation** to refer to child properties of an object, including the properties of embedded objects and relationships: @@ -122,32 +126,10 @@ property ``address``. You can chain dot notations to query the deeply nested .. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.deep-dot-notation.ts.rst - - -.. _rql-parameterized-queries: - -Parameterized vs. Serialized Queries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can format queries in two ways: - -- **Serialized queries** pass values directly in the expression. - -.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.serialized-query.ts.rst - -- **Parameterized queries** pass interpolated variables as additional - arguments. The syntax for interpolated variables is - ``$``, starting at ``0`` and incrementing for each additional variable. - -.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.predicate.ts.rst - -Supported Types -~~~~~~~~~~~~~~~ - .. _rql-nil-type: Nil Type -```````` +~~~~~~~~ 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. @@ -177,26 +159,37 @@ Use comparison operators to compare values of matching data types. * - Operator - Description - * - ``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. + * - ``BETWEEN {X, Y}`` + - Evaluates to ``true`` if the left-hand expression (``X``) + is between or equal to the right-hand expression (``Y``) range. + + - For dates, this evaluates to ``true`` if the left-hand date is within the right-hand date range. + - For strings, this evaluates to ``true`` if the left-hand string is + lexicographically within the right-hand range. * - | ``==``, ``=`` - Evaluates to ``true`` if the left-hand expression is equal to the right-hand expression. + - For strings, this evaluates to ``true`` if the left-hand string is + lexicographically equal to the right-hand string. + * - | ``>`` - 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. + + - For dates, this evaluates to ``true`` if the left-hand date is later + than the right-hand date. + - For strings, this evaluates to ``true`` if the left-hand string is + lexicographically greater than the right-hand string. * - | ``>=`` - - 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 + - Evaluates to ``true`` if the left-hand expression + is greater than or equal to the right-hand expression. + + - For dates, this evaluates to ``true`` if the left-hand date is later than or the same as the right-hand date. + - For strings, this evaluates to ``true`` if the left-hand string is lexicographically greater than or equal to the right-hand string. * - | ``IN`` - Evaluates to ``true`` if the left-hand expression is in the @@ -206,14 +199,18 @@ Use comparison operators to compare values of matching data types. * - | ``<`` - 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. + + - For dates, this evaluates to ``true`` if the left-hand date is earlier + than the right-hand date. + - For strings, this evaluates to ``true`` if the left-hand string is lexicographically less than the right-hand string. * - | ``<=`` - 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. + 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. + - For strings, this evaluates to ``true`` if the left-hand string is lexicographically less than or equal to the right-hand string. * - | ``!=``, ``<>`` - Evaluates to ``true`` if the left-hand expression is not equal @@ -229,7 +226,7 @@ property values match certain criteria: 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: + failure with a message similar to the following: .. code-block:: :copyable: false @@ -241,84 +238,12 @@ property values match certain criteria: including decimal, float, and Decimal128. -.. _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' - - .. literalinclude:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.string-operators.js - :language: javascript - .. _rql-logical-operators: Logical Operators ~~~~~~~~~~~~~~~~~ -Make compound predicates using logical operators. +Use logical operators to create compound predicates. .. list-table:: :header-rows: 1 @@ -327,16 +252,13 @@ Make compound predicates using logical operators. * - Operator - Description - * - | ``AND`` - | ``&&`` + * - | ``AND`` | ``&&`` - Evaluates to ``true`` if both left-hand and right-hand expressions are ``true``. - * - | ``NOT`` - | ``!`` + * - | ``NOT`` | ``!`` - Negates the result of the given expression. - * - | ``OR`` - | ``||`` + * - | ``OR`` | ``||`` - Evaluates to ``true`` if either expression returns ``true``. The following example uses logical operators to combine multiple predicates: @@ -379,8 +301,9 @@ Aggregate Operators ~~~~~~~~~~~~~~~~~~~ .. TODO: link to collection query section -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 +Use aggregate operators to 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 @@ -409,60 +332,48 @@ You can use aggregate operators on collection properties, such as a list, or on - Evaluates to the sum of a given numerical property across a collection, excluding ``null`` values. - The following example uses aggregate operators to find projects whose ``items`` collection property meets certain criteria: .. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.aggregate-operators.ts.rst -.. _rql-sort-distinct-limit: +.. _rql-collection-operators: -Sort, Distinct, and Limit Operators -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Collection Operators +~~~~~~~~~~~~~~~~~~~~ -Use sort, distinct, and limit operators to shape your query results collection. You can -combine these operators in a single query across multiple properties. Operators -are applied in the order they appear in the query. +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: 20 80 + :widths: 30 70 * - Operator - Description - * - ``SORT`` (``ASC`` or ``DESC``) - - Sort the results collection by the specified property or properties, either in ascending (``ASC``) or descending - (``DESC``) order. Separate multiple properties by comma and define the - sort order for each property. The SDK applies each sort operation one at a time, in order. - - * - ``DISTINCT`` - - Remove duplicates of the specified property or properties from the - results collection. Separate multiple properties by comma. The SDK - applies all distinct operations as a single AND condition, - where duplicates must match all specified properties. - - * - ``LIMIT`` - - Limit the results collection to the specified number. + * - ``ALL`` + - Returns objects where the predicate evaluates to ``true`` for all objects + in the collection. -The following example finds all incomplete items, then -shapes the returned results using sort, distinct, and limit operators: + * - ``ANY``, ``SOME`` + - Returns objects where the predicate evaluates to ``true`` for any objects + in the collection. -.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit.ts.rst + * - ``NONE`` + - Returns objects where the predicate evaluates to false for all objects + in the collection. -.. important:: Order Matters +The following example uses collection operators to find projects whose ``items`` +collection property meets certain criteria - The SDK executes queries in order. This includes the order of any ``SORT``, ``DISTINCT``, and ``LIMIT`` operators in - the query *and* the order of any properties within those operators. - 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:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.set-operators.ts.rst - .. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit-order-matters.ts.rst - -Data Type Operators -------------------- +Type-Specific Operators +----------------------- .. _rql-type-operator: @@ -493,13 +404,444 @@ The following example uses the ``@type`` operator to find projects whose mixed data type ``additionalInfo`` property type matches specific criteria: -.. literalinclude:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.type-operator.js - :language: js +.. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.type-operator.ts.rst + + +.. _rql-dictionary-operators: + +Dictionary Operators +~~~~~~~~~~~~~~~~~~~~ + +Use dictionary operators in combination with +:ref:`comparison operators ` to filter objects +based on dictionary keys and values. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Operator + - Description + + * - ``@values`` + - Returns objects that have a specified dictionary value. + + * - ``@keys`` + - Returns objects that have a specified dictionary key. + + * - ``@size``, ``@count`` + - The number of elements in a dictionary. + + * - ``Dictionary['key']`` + - The value of a dictionary key. + + * - ``ALL | ANY | NONE .@type`` + - Checks if the dictionary contains properties of certain type. + +The following example uses dictionary operators with comparison operators to find projects based on the ``comments`` dictionary property: + + .. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.dictionary-operators.ts.rst + +.. _rql-string-operators: + +String Operators +~~~~~~~~~~~~~~~~ + +Use string operators or :ref:`comparison operators ` +to filter objects based on string values. SDKs evaluate string values +:wikipedia:`lexicographically `. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Operator or Modifier + - Description + + * - | ``BEGINSWITH`` + - Evaluates to ``true`` if the left-hand string begins with + the right-hand string. This is similar to ``contains``, + but only matches if the right-hand string is found + at the beginning of the left-hand string. + * - | ``CONTAINS`` + - Evaluates to ``true`` if the right-hand string + is found anywhere in the left-hand string. -Data Type Queries ------------------ + * - | ``ENDSWITH`` + - Evaluates to ``true`` if the left-hand string ends + with the right-hand string. This is similar to ``contains``, + but only matches if the left-hand string is found + at the very end of the right-hand string. + * - | ``LIKE`` + - Evaluates to ``true`` if the left-hand string + matches the right-hand string wildcard string. 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". + * - | ``[c]`` + - Modifier that indicates a string value is *not* case sensitive. +The following example uses string and comparison operators to find projects +based on the project name: + + .. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.string-operators.ts.rst + +.. tip:: String Values are Case Sensitive + + String values are case sensitive by default. Use the ``[c]`` modifier to specify that values are *not* case sensitive. + +.. _rql-list-queries: + +List Comparisons +~~~~~~~~~~~~~~~~ + +Use :ref:`comparison operators ` and +:ref:`collection operators ` to filter based +on lists of data. + +You can compare any type of valid list, including: + +- Collections of objects, which let you filter against other data + in the database. + + .. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-collection.ts.rst + +- 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. + + .. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-static.ts.rst + +- Native list objects passed in a :ref:`parameterized expression + `, which let you pass application data + directly to your queries. + + .. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.list-comparisons-parameterized.ts.rst + +.. note:: Defaults to ``ANY`` + + If you do not define a collection operator, a list expression defaults + to the ``ANY`` operator. + + .. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.equivalent-lists-any-operator.ts.rst + +The following table demonstrates 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-objectid-uuid-operators: + +ObjectId and UUID Comparisons +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use equality (``==`` and ``!=``) :ref:`comparison operators ` to compare :manual:`BSON ObjectIds ` and +:manual:`UUIDs `. These data types are often used as +primary keys. + +You can use pass ``ObjectId`` and ``UUID`` values either as parameterized query +arguments or to the ``oid()`` or ``uuid()`` methods, respectively. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Operator + - Description + + * - | ``oid()`` + - The string representation of the ``ObjectID`` to evaluate. + + * - | ``uuid()`` + - The string representation of the ``UUID`` to evaluate. + +The following examples use equality comparison operators to find items based on their ``_id`` property: + +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.oid.ts.rst + +.. _rql-date-operators: + +Date Comparisons +~~~~~~~~~~~~~~~~ + +Use :ref:`comparison operators ` to query date types. + +Specify dates in the following formats: + +- As a date in UTC, with the date and time separated by ``@`` or ``T``: ``YYYY-MM-DD@HH:mm:ss:nnnnnnnnnn`` (year-month-day@hours:minutes:seconds:nanoseconds), UTC. +- As a time in seconds since the :wikipedia:`Unix epoch `: ``Ts:n`` (``T`` designates the start of the time, + ``s`` is the number of seconds, and ``n`` is the number of nanoseconds). + +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.date-alt-representation.ts.rst + +The following example uses a parameterized query to find items based on a new ``dateCreated`` property that populates when an item is marked as complete: + + .. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.date-parameterized-query.ts.rest + +.. tip:: Parameterize Date Queries + + We recommend using a parameterized query to pass the date data type from the SDK language you are using to your query. + +.. _rql-backlinks: + +Backlink Queries +~~~~~~~~~~~~~~~~ + +A **backlink** is an :ref:`inverse relationship ` link that lets +you query 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. + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Operator + - Description + + * - ``@links`` + - Accesses the backlink of a relationship specified by the object type and + property name (``@links..``). + * - ``@count`` + - The number of elements in a backlink collection. You can use the + ``@count`` operator directly on ``@links`` to query the count of all relationships that point to an object. + +You can access backlinks: + +- Using the ``@links..`` syntax, where + ```` and ```` refer to a specific property on an + object type that references the queried object type. + + .. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-atLinks.ts.rst + +- Using the ``linkingObjects`` property to explicitly include the backlink in your data model. This lets you reference the backlink through an assigned property name using :ref:`dot notation `. + + .. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-linkingObjects.ts.rst + +The result of a backlink is treated like a collection and supports +:ref:`collection operators ` and :ref:`aggregate operators `. + +The following examples find items based on the projects they belong to through the ``@links`` operator or the ``projects`` property: + +.. include:: /generated/node/v12/formatted/realm-query-language.test.snippet.backlinks-collection-operators.ts.rst + +.. _rql-fts: + +Full Text Search (FTS) Queries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Perform boolean match word searches to query on properties that have a full-text +search (FTS) annotation. For information on enabling FTS on a property, refer to +:ref:`sdks-fts-property`. + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Operator + - Description + + * - ``TEXT`` + - Evaluates to ``true`` if the left-hand FTS-enabled string property + matches the right-hand string or wildcard string. 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 that occur + after the string. + - The ``-`` wildcard matches all characters for exclusion from results. + +Query strings are converted to tokens by a tokenizer using the following rules: + +- Tokens can only consist of characters from ASCII and the Latin-1 supplement (western languages). All other characters are considered whitespace. +- Strings split by a hyphen (``-``) are split into two tokens. For example, ``full-text`` splits into ``full`` and ``text``. +- Tokens are diacritics insensitive and case insensitive. + +You can search for entire words or phrases, or limit your results with the +following wildcard characters: + +- Exclude results for a word by placing the ``-`` character in front of the word. +- Specify prefixes by placing the ``*`` wildcard at the end of a prefix. Suffix + searching is not currently supported. + +The following example uses the ``TEXT`` operator to find items based on their FTS-enabled +``name`` property: + +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.test.snippet.rql-fts.ts.rst + +.. _rql-geospatial: + +Geospatial Queries +~~~~~~~~~~~~~~~~~~ + +Use the ``geoWithin`` operator to query geospatial data. For more information on +defining and working with geospatial data, refer to :ref:`sdks-define-geospatial-object`. + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Operator + - Description + + * - ``geoWithin`` + - Returns objects where the latitude/longitude pair in a custom embedded object's ``coordinates`` property + is contained within a specified geospatial shape. + The following geospatial shapes are supported: + + - ``GeoCircle`` + - ``GeoBox`` + - ``GeoPolygon`` + +The following example compares the coordinates of +the embedded ``location`` property against the boundaries of the ``GeoCircle`` +shape named +``smallCircle``: + +.. include:: /generated/node/v12/geospatial.test.snippet.rql-geospatial.ts.rst + +.. important:: Geospatial Data Does Not Support Parameterized Queries + + You cannot use parameterized queries with geospatial data. + +.. _rql-subqueries: + +List Subqueries +~~~~~~~~~~~~~~~ + +Use the ``SUBQUERY()`` predicate function to iterate through list properties +with an additional query. Subqueries are useful when you need to match objects +in a list property based on multiple conditions. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Operator + - Description + + * - ``SUBQUERY(, $, )`` + - Returns list objects for the specified collection where the predicate + evaluates to ``true``. + + - ``collection``: The name of the list property to iterate through. + - ``variableName``: A variable name of the element to use in the + subquery, prefixed with ``$``. + - ``predicate``: The subquery predicate. + Use the variable specified by ``variableName`` to refer to the + currently-iterated element. + + * - ``@count`` + - The number of objects in the subquery results collection. This is + required for subquery filters. + +Subqueries require the ``@count`` aggregate operator. You can use the count of the subquery result as you would any other number in a valid expression. + +The following example uses subquery filters to find projects based on the +``items`` collection property using the ``$item`` variable name: + +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.subquery.ts.rst + +.. tip:: Compare Count to ``0`` to Return All Matching Objects + + The ``@count`` aggregate operator returns the number of objects in the + subquery results collection. You can compare the count with the number ``0`` to return all matching objects. + +.. _rql-sort-distinct-limit: + +Sort, Distinct, and Limit Operators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use sort, distinct, and limit operators to shape your query results collection. You can +combine these operators in a single query across multiple properties. Operators +are applied in the order they appear in the query. + +.. list-table:: + :header-rows: 1 + :widths: 20 80 + + * - Operator + - Description + + * - ``SORT`` (``ASC`` or ``DESC``) + - Sort the results collection by the specified property or properties, either in ascending (``ASC``) or descending + (``DESC``) order. Separate multiple properties by comma and define the + sort order for each property. The SDK applies each sort operation one at a time, in order. + + * - ``DISTINCT`` + - Remove duplicates of the specified property or properties from the + results collection. Separate multiple properties by comma. The SDK + applies all distinct operations as a single AND condition, + where duplicates must match all specified properties. + + * - ``LIMIT`` + - Limit the results collection to the specified number. + +The following example finds all incomplete items, then +shapes the returned results using sort, distinct, and limit operators: + +.. include:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit.ts.rst + +.. important:: Order Matters + + The SDK executes queries in order. This includes the order of any ``SORT``, ``DISTINCT``, and ``LIMIT`` operators in + the query *and* the order of any properties within those operators. + 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:: /examples/generated/node/v12/formatted/realm-query-language.test.snippet.sort-distinct-limit-order-matters.ts.rst