Docs 菜单
Docs 主页
/ /
Atlas Device SDKs

Realm 查询语言

在此页面上

  • 使用 Realm SDK 进行查询
  • 本页中的示例
  • 表达式
  • 参数化查询
  • 查询格式
  • 点符号
  • Nil 类型
  • 比较操作符。
  • 逻辑操作符
  • 字符串操作符
  • ObjectId 和 UUID 操作符
  • 算术操作符
  • 类型操作符
  • 字典操作符
  • 日期操作符
  • 聚合操作符
  • 集合操作符
  • 列表比较
  • 全文本搜索
  • 全文搜索分词器详细信息
  • 地理空间查询
  • 反向链接查询
  • 子查询
  • 排序、去重和限制
  • 灵活同步 RQL 限制
  • 已索引可查询字段订阅的要求
  • 灵活同步中不支持的查询运算符
  • 列出查询
  • 嵌入式对象或关联对象
  • 查询大小限制

RQL ( RQL ) 是一种基于字符串的查询语言,用于在从域检索对象时限制搜索。 SDK 特定的方法将查询传递给Realm查询引擎,该引擎从域中检索匹配的对象。 RQL语法基于 NSPredicate。

查询会为所查询的集合中的每个对象评估谓词。如果谓词解析为 true,则结果集合将包含该对象。

您可以通过 SDK 的过滤器或查询方法,在大多数 Realm SDK 中使用 Realm 查询语言。Swift SDK 是一个例外,因为它使用 NSPredicate 查询 API。某些 SDK 还支持使用符合其语言特点的 API 来进行 Realm 查询。

如需进一步了解不同 SDK 查询域的特定方法,请参阅相应的 SDK 文档:

C++ SDK目前仅实现RQL的一个子集。 有关在C++ SDK中查询Realm的示例,请参阅:

注意

Swift SDK 不支持 Realm 查询语言

Swift SDK 不支持使用 Realm 查询语言进行查询。您可以改用 NSPredicate 查询 Realm。有关在 Swift SDK 中查询 Realm 的示例,请参阅筛选数据 - Swift SDK

您还可以使用 Realm 查询语言在 Realm Studio 中浏览数据。Realm Studio 是一款用于查看、编辑和设计 Realm 文件的可视化工具。

本页面中的许多示例都使用了一个待办事项列表应用的简单数据集。两种 Realm 对象类型分别是 ProjectItem

  • Item 具有名称、受让人名称和已完成标志。其中还有一个任意的优先级数字(数值越高表示越重要)以及处理所花费的分钟数。

  • Project 具有零个或多个 Items 以及一个可选配额,用于指示预计要完成的待办事项的最小数量。

请参阅 ProjectItem 这两个类的模式,如下所示:

public class Item extends RealmObject {
ObjectId id = new ObjectId();
String name;
Boolean isComplete = false;
String assignee;
Integer priority = 0;
Integer progressMinutes = 0;
@LinkingObjects("items")
final RealmResults<Project> projects = null;
}
public class Project extends RealmObject {
ObjectId id = new ObjectId();
String name;
RealmList<Item> items;
Integer quota = null;
}
open class Item(): RealmObject() {
var id: ObjectId = new ObjectId()
@FullText
lateinit var name: String
var isComplete: Boolean = false
var assignee: String? = null
var priority: Int = 0
var progressMinutes: Int = 0
}
open class Project(): RealmObject() {
var id: ObjectId = new ObjectId()
lateinit var name: String
lateinit var items: RealmList<Item>
var quota: Int? = null
}
public class Item : RealmObject
{
[PrimaryKey]
[MapTo("_id")]
public ObjectId Id { get; set; } = ObjectId.GenerateNewId();
[MapTo("name")]
[Indexed(IndexType.FullText)]
public string Name { get; set; }
[MapTo("isComplete")]
public bool IsComplete { get; set; } = false;
[MapTo("assignee")]
public string Assignee { get; set; }
[MapTo("priority")]
public int Priority { get; set; } = 0;
[MapTo("progressMinutes")]
public int ProgressMinutes { get; set; } = 0;
[MapTo("projects")]
[Backlink(nameof(Project.Items))]
public IQueryable<Project> Projects { get; }
}
public class Project : RealmObject
{
[PrimaryKey]
[MapTo("_id")]
public ObjectId Id { get; set; } = ObjectId.GenerateNewId();
[MapTo("name")]
public string Name { get; set; }
[MapTo("items")]
public IList<Item> Items { get; }
[MapTo("quota")]
public int Quota { get; set; }
}
const ItemModel = {
name: "Item",
properties: {
id: "objectId",
name: {type: "string", indexed: "full-text"},
isComplete: { type: "bool", default: false },
assignee: "string?",
priority: {
type: "int",
default: 0,
},
progressMinutes: {
type: "int",
default: 0,
},
projects: {
type: "linkingObjects",
objectType: "Project",
property: "items",
},
},
primaryKey: "id",
};
const ProjectModel = {
name: "Project",
properties: {
id: "objectId",
name: "string",
items: "Item[]",
quota: "int?",
},
primaryKey: "id",
};
const ItemModel = {
name: "Item",
properties: {
id: "objectId",
name: {type: "string", indexed: "full-text"},
isComplete: { type: "bool", default: false },
assignee: "string?",
priority: {
type: "int",
default: 0,
},
progressMinutes: {
type: "int",
default: 0,
},
projects: {
type: "linkingObjects",
objectType: "Project",
property: "items",
},
},
primaryKey: "id",
};
const ProjectModel = {
name: "Project",
properties: {
id: "objectId",
name: "string",
items: "Item[]",
quota: "int?",
},
primaryKey: "id",
};
class Item(): RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
@FullText
var name: String = ""
var isComplete: Boolean = false
var assignee: String? = null
var priority: Int = 0
var progressMinutes: Int = 0
}
class Project(): RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
var items: RealmList<Item> = realmListOf<Item>()
var quota: Int? = null
}
part 'models.realm.dart';
@RealmModel()
class _Project {
@MapTo("_id")
@PrimaryKey()
late ObjectId id;
late String name;
late List<_Item> items;
int? quota;
}
@RealmModel()
class _Item {
@MapTo("_id")
@PrimaryKey()
late ObjectId id;
@Indexed(RealmIndexType.fullText)
late String name;
bool isComplete = false;
String? assignee;
int priority = 0;
int progressMinutes = 0;
}

过滤器由谓词中的表达式组成。表达式由以下任一内容组成:

  • 当前正在评估的对象的某个属性的名称。

  • 一个操作符和最多两个参数表达式。例如,在表达式 A + B 中,整个 A + B 是一个表达式,但 AB 也是操作符 + 的参数表达式。

  • 一个值,例如字符串 ('hello') 或数字 (5)。

"progressMinutes > 1 AND assignee == $0", "Ali"

创建参数化查询以将变量插入到准备好的 Realm 查询语言语句中。插值变量的语法是 $<int>,从 0开始。将位置参数作为附加参数传递给使用 Realm 查询语言的 Realm SDK 方法。

仅包含一个带有 $0 的参数。

"progressMinutes > 1 AND assignee == $0", "Ali"

包含多个参数,使用从 $0 开始的升序整数。

"progressMinutes > $0 AND assignee == $1", 1, "Alex"

下表展示了在对以下数据类型进行序列化和参数化时,应如何设置查询的格式:

类型
参数化示例
序列化示例
注意
布尔
"setting == $0", false
"setting == false"
truefalse值。
"name == $0", "George"
"name == 'George'"
适用于 stringchar 数据类型。
"age > $0", 5.50
"age > 5.50"
适用于 intshortlongdoubleDecimal128float 数据类型。
"date < $0", dateObject
"date < 2021-02-20@17:30:15:0"

对于参数化日期查询,必须传入日期对象。对于序列化日期查询,可以采用以下格式表示日期:

  • 作为明确的日期和时间 — YYYY-MM-DD@HH:mm:ss:nn(年-月-日@小时:分钟:秒:纳秒)

  • datetime作为相对于 Unix 纪元 的 - Ts:n(T,指定时间开始;s ,秒;n ,纳秒)

  • 参数化 Date 对象

"_id == $0", oidValue
"_id == oid(507f1f77bcf86cd799439011)"
对于参数化 ObjectId 查询,您必须传入 ObjectId。对于序列化 ObjectId 查询,字符串表示形式为 oid(<ObjectId String>)
"id == $0", uuidValue
"id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)"
对于参数化 UUID 查询,您必须传入 UUID。对于序列化 UUID 查询,字符串表示为 uuid(<UUID String>)
二进制文件
"value == $0", "binary"
"value == 'binary'"
对于 ASCII 字符,RQL 将其二进制值序列化为带引号的字符串。对于不可打印的字符,RQL 将其二进制值序列化为 Base 64 值。
"ANY items.name == {$0, $1}", "milk", "bread"
"ANY items.name == {'milk', 'bread'}"
适用于列表(lists)、集合(collections)和集(sets)。应该为列表中的每个成员使用参数化值。
RealmObject
"ANY items == $0", obj("Item", oid(6489f036f7bd0546377303ab))
"ANY items == obj('Item', oid(6489f036f7bd0546377303ab))"
要传入 RealMobject,您需要对象的类和主键。

在引用对象属性时,可以使用点符号来引用该对象的子属性。您甚至可以使用点符号来引用嵌入式对象的属性和关系。

例如,请考虑针对某个对象的查询,该对象具有一个 workplace 属性,该属性引用了一个 Workplace 对象。Workplace 对象具有嵌入式对象属性 address。您可以使用链式点符号来引用该地址的 zipcode 属性:

"workplace.address.zipcode == 10019"

Realm 查询语言包含用于表示空指针的 nil 类型。您可以在查询中直接引用 nil,也可以通过参数化查询引用。如果使用参数化查询,每个 SDK 都会将各自的空指针映射到 nil

"assignee == nil"
// comparison to language null pointer
"assignee == $0", null

搜索中最直接的操作就是比较值。

重要

类型必须匹配

操作符两侧的类型必须相同。例如,将 ObjectId 与字符串进行比较会导致前提条件失败,并显示类似于下方的消息:

"Expected object of type object id for property 'id' on object of type
'User', but received: 11223344556677889900aabb (Invalid value)"

您可以选取任意两种数值类型进行比较,包括十进制数、浮点数和 Decimal128。

Operator
说明
BETWEEN {number1, number2}
如果左侧数值或日期表达式的结果在右侧范围内或落在该范围上,则计算结果为 true。对于日期,如果左侧日期在右侧日期范围内,则计算结果为 true
==, =
如果左侧表达式等于右侧表达式,则计算结果为 true
>
如果左侧的数值或日期表达式大于右侧的数值或日期表达式,则计算结果为 true。对于日期,如果左侧日期晚于右侧日期,则计算结果为 true
>=
如果左侧数值或日期表达式大于或等于右侧数值或日期表达式,则计算结果为 true。对于日期,如果左侧日期晚于或等于右侧日期,则计算结果为 true
IN
如果左侧表达式在右侧列表中,则计算结果为 true。这等同于 == ANY,相当于其简写形式。
<
如果左侧数值或日期表达式小于右侧数值或日期表达式,则计算结果为 true。对于日期,如果左侧日期早于右侧日期,则计算结果为 true
<=
如果左侧数值表达式小于或等于右侧数值表达式,则计算结果为 true。对于日期,如果左侧日期早于或等于右侧日期,则计算结果为 true
!=, <>
如果左侧表达式不等于右侧表达式,则计算结果为 true

例子

下面的示例使用 Realm 查询语言的比较操作符执行以下操作:

  • 通过将 priority 属性值与阈值数字进行比较来查找高优先级待办事项,高于该阈值的优先级可以被视为高优先级。

  • 通过查看 progressMinutes 属性是否等于或大于特定值来查找长时间运行的待办事项。

  • 通过查找 assignee 属性等于 null 的待办事项来查找未分配的待办事项。

  • 通过查询 progressMinutes 属性介于两个数字之间的项目来查找一定时间范围内的待办事项。

  • 从给定列表中查找具有特定 progressMinutes 值的待办事项。

// Find high priority to-do items by comparing the value of the ``priority``
// property value with a threshold number, above which priority can be considered high.
"priority > $0", 5
// Find long-running to-do items by seeing if the progressMinutes property is at or above a certain value.
"progressMinutes > $0", 120
// Find unassigned to-do items by finding items where the assignee property is equal to null.
"assignee == $0", null
// Find to-do items within a certain time range by finding items
// where the progressMinutes property is between two numbers.
"progressMinutes BETWEEN { $0 , $1 }", 30, 60
// Find to-do items with a certain amount of progressMinutes from the given list.
"progressMinutes IN { $0, $1, $2, $3, $4, $5 }", 10, 20, 30, 40, 50, 60

使用逻辑操作符创建复合谓词。

Operator
说明
AND
&&
如果左侧和右侧表达式的值均为 true,则计算结果为 true
NOT
!
对给定表达式的结果予以否定。
OR
||
如果任一表达式返回 true,则计算结果为 true

例子

我们可以使用查询语言的逻辑操作符来查找 Ali 已完成的所有任务。也就是说,我们查找 assignee 属性值等于“Ali”且 isComplete 属性值为 true 的所有项目:

"assignee == $0 AND isComplete == $1", "Ali", true

使用这些字符串操作符比较字符串值。类似正则表达式的通配符可以让搜索变得更加灵活。

注意

您可以将以下修饰符与字符串操作符一起使用:

  • [c] 不区分大小写。

    "name CONTAINS[c] $0", 'a'
Operator
说明
BEGINSWITH
如果左侧字符串表达式以右侧字符串表达式开头,则计算结果为 true。这与 contains 类似,但仅当在左侧字符串表达式的开头找到右侧字符串表达式时才匹配。
CONTAINS
如果在左侧字符串表达式中的任意位置找到右侧字符串表达式,则计算结果为 true
ENDSWITH
如果左侧字符串表达式以右侧字符串表达式结尾,则计算结果为 true。这与 contains 类似,但仅当在右侧字符串表达式的最末尾找到左侧字符串表达式时才匹配。
LIKE

如果左侧字符串表达式与右侧字符串通配符字符串表达式匹配,则计算结果为 true。通配符字符串表达式是使用普通字符和两个特殊通配符的字符串:

  • * 通配符可与零个或多个任意字符匹配

  • ? 通配符与任意字符匹配。

例如,通配符字符串“d?g”匹配“dog”、“dig”和“dug”,但不匹配“ding”、“dg”或“a dog”。

==, =
如果左侧字符串在字典顺序上等于右侧字符串,则计算结果为 true
!=, <>
如果左侧字符串在字典顺序上不等于右侧字符串,则计算结果为 true

例子

我们使用查询引擎的字符串操作符来查找:

  • 名称以字母“e”开头的项目

  • 名称中包含“ie”的项目

"name BEGINSWITH[c] $0", 'e'
"name CONTAINS $0", 'ie'

查询 BSON ObjectIdsUUID。这些数据类型通常用作主键。

要使用 ObjectId 进行查询,请使用参数化查询。请将您要查询的 ObjectId 或 UUID 作为参数传递。

"_id == $0", oidValue

您还可以将要评估的 ObjectId 的字符串表示形式放在 oid(<ObjectId String>) 中。

"_id == oid(6001c033600510df3bbfd864)"

要使用 UUID 进行查询,请将您要评估的 UUID 的字符串表示形式放在 uuid(<UUID String>) 中。

"id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)"
Operator
说明
==, =
如果左侧值等于右侧值,则计算结果为 true
!=, <>
如果左侧值不等于右侧值,则计算结果为 true

评估数值数据类型时,请在 RQL 表达式的一侧执行基本算数运算。

"2 * priority > 6"
// Is equivalent to
"priority >= 2 * (2 - 1) + 2"

您还可以在数学运算中同时使用多个对象属性。

"progressMinutes * priority == 90"
Operator
说明
*
乘法。
/
除法。
+
添加。
-
减法。
()
将表达式分组在一起。

使用 @type 操作符检查属性的类型。您只能将类型操作符与混合类型和字典一起使用。

根据数据类型名称的字符串表示对属性进行评估。请参阅 SDK 文档,以了解如何将 SDK 对应语言中定义的数据类型映射到 Realm 支持的数据类型。

Operator
说明
@type
检查属性的类型是否为字符串形式的属性名称。使用 ==!= 比较相等性。
"mixedType.@type == 'string'"
"mixedType.@type == 'bool'"

使用这些字典操作符比较字典值。

Operator
说明
@values
返回具有右侧表达式中指定值的对象。
@keys
返回具有右侧表达式中指定键的对象。
@size, @count
字典中的元素数量。
Dictionary['key']
访问字典中某个键对应的值。
ALL | ANY | NONE <property>.@type
检查字典是否包含特定类型的属性。

您还可以将字典操作符与比较操作符结合使用,根据字典键和值筛选对象。 以下示例展示了将字典操作符与比较操作符结合使用的一些方法。 所有示例均查询具有名为dict的字典属性的 Realm 对象集合。

例子

以下示例使用各种字典操作符。

// Evaluates if there is a dictionary key with the name 'foo'
"ANY dict.@keys == $0", 'foo'
// Evaluates if there is a dictionary key with key 'foo' and value 'bar
"dict['foo'] == $0", 'bar'
// Evaluates if there is greater than one key-value pair in the dictionary
"dict.@count > $0", 1
// Evaluates if dictionary has property of type 'string'
"ANY dict.@type == 'string'"
// Evaluates if all the dictionary's values are integers
"ALL dict.@type == 'bool'"
// Evaluates if dictionary does not have any values of type int
"NONE dict.@type == 'double'"
// ANY is implied.
"dict.@type == 'string'"

查询 Realm 中的日期类型。

通常,应当通过参数化查询将日期数据类型从您所使用 SDK 的对应语言传递到查询。

"timeCompleted < $0", someDate

您还可以通过以下两种方式指定日期:

  • 作为特定日期(以 UTC 为单位)- YYYY-MM-DD@HH:mm:ss:nnnnnnnnnn (year-month-day@hours:minutes:seconds:nanoseconds), UTC。 您还可以使用T代替@来分隔日期和时间。

  • Unix 纪元 以来的时间(以秒为单位) -Ts:n ,其中T s表示时间开始,n 为秒数, 为纳秒数。

日期支持比较操作符。

例子

以下示例将展示如何使用带有日期对象的参数化查询:

var date = new Date("2021-02-20@17:30:15:0");
"timeCompleted > $0", date

将聚合操作符应用于 Realm 对象的集合属性。聚合操作符遍历集合并将其归约为单个值。

Operator
说明
@avg
计算集合中给定数值属性的平均值。如果任何值为 null,则它们不会计入结果。
@count
计算给定集合中的对象数量。
@max
计算集合中给定数值属性的最大值。null 值将被忽略。
@min
计算集合中给定数值属性的最小值。null 值将被忽略。
@sum
计算整个集合中给定数值属性的总和,不包括 null 值。

例子

下面这些示例将对内含待办事项的项目对象进行查询。查询的结果将分别满足以下条件:

  • 平均事项优先级大于 5 的项目。

  • 包含优先级小于 5 的事项的项目。

  • 包含优先级大于 5 的事项的项目。

  • 包含 5 个以上事项的项目。

  • 包含长时间运行事项的项目。

var priorityNum = 5;
"items.@avg.priority > $0", priorityNum
"items.@max.priority < $0", priorityNum
"items.@min.priority > $0", priorityNum
"items.@count > $0", 5
"items.@sum.progressMinutes > $0", 100

通过集合操作符,可以查询对象集合中的列表属性。集合操作符通过将谓词应用于对象的给定列表属性的每个元素来过滤集合。如果谓词返回 true,则相应对象包含在输出集合中。

Operator
说明
ALL
如果集合中所有对象的谓词计算结果均为 true,则返回相应对象。
ANY, SOME
如果集合中任一对象的谓词计算结果为 true,则返回相应对象。
NONE
如果集合中所有对象的谓词评估结果均为 false,则返回相应对象。

例子

此示例使用集合操作符查找包含符合指定条件的待办事项的项目:

// Projects with no complete items.
"NONE items.isComplete == $0", true
// Projects that contain a item with priority 10
"ANY items.priority == $0", 10
// Projects that only contain completed items
"ALL items.isComplete == $0", true
// Projects with at least one item assigned to either Alex or Ali
"ANY items.assignee IN { $0 , $1 }", "Alex", "Ali"
// Projects with no items assigned to either Alex or Ali
"NONE items.assignee IN { $0 , $1 }", "Alex", "Ali"

您可以使用比较操作符集合操作符来根据数据列表进行过滤。

您可以比较任何类型的有效列表。这包括:

  • Realm Object的集合,让您可以针对域中的其他数据进行过滤。

    "oid(631a072f75120729dc9223d9) IN items.id"
  • 直接在查询中定义的列表,用于过滤静态数据。您可以使用在左大括号 ({) 和右大括号 (}) 中使用逗号分隔的字面值列表来定义静态列表。

    "priority IN {0, 1, 2}"
  • 通过参数化表达式传递的原生列表对象,可允许您将应用程序数据直接传递给查询。

    const ids = [
    new BSON.ObjectId("631a072f75120729dc9223d9"),
    new BSON.ObjectId("631a0737c98f89f5b81cd24d"),
    new BSON.ObjectId("631a073c833a34ade21db2b2"),
    ];
    const parameterizedQuery = realm.objects("Item").filtered("id IN $0", ids);

如果未定义集合操作符,则列表表达式默认为 ANY 操作符。

例子

这两个列表查询是等效的:

  • age == ANY {18, 21}

  • age == {18, 21}

这两个查询都返回年龄属性等于 18 或 21 的 Realm 对象。您也可以执行相反的操作,仅在年龄不等于 18 或 21 时才返回对象:

  • age == NONE {18, 21}

下表中的示例展示了集合操作符如何与列表以及比较运算符搭配使用:

表达式(expression)
匹配?
原因
ANY {1, 2, 3} > ALL {1, 2}
true
左侧的某个值(3)大于右侧的值(1 和 2)
ANY {1, 2, 3} == NONE {1, 2}
true
3 并不匹配 1 或 2
ANY {4, 8} == ANY {5, 9, 11}
false
4 和 8 均不匹配右侧的任何值(5、9 或 11)
ANY {1, 2, 7} <= NONE {1, 2}
true
左侧的某个值(7)不小于也不等于 1 和 2
ALL {1, 2} IN ANY {1, 2, 3}
true
左侧的每个值(1 和 2)都等于 1、2 或 3
ALL {3, 1, 4, 3} == NONE {1, 2}
false
1 匹配 NONE 列表中的某个值(1 或 2)
ALL {} in ALL {1, 2}
true
一个空列表可以匹配所有列表
NONE {1, 2, 3, 12} > ALL {5, 9, 11}
false
12 大于右侧的所有值(5、9 和 11)
NONE {4, 8} > ALL {5, 9, 11}
true
4 和 8 都小于右侧的某个值(5、9 或 11)
NONE {0, 1} < NONE {1, 2}
true
0 和 1 都不小于 1 和 2

您可以使用 RQL 查询带有全文搜索 (FTS) 注解的属性。FTS 支持布尔匹配词搜索,而不支持相关性搜索。有关在属性上启用 FTS 的信息,请参阅您的 SDK 的 FTS 文档:

要查询这些属性,请在查询中使用 TEXT 谓词。

您可以搜索整个单词或短语,或使用以下字符限制搜索结果:

  • 在单词前加上 - 字符以排除该单词的结果。

  • 通过在前缀末尾添加 * 字符来指定前缀。目前不支持后缀搜索。

在以下示例中,我们查询 Item.name 属性:

// Filter for items with 'write' in the name
"name TEXT $0", "write"
// Find items with 'write' but not 'tests' using '-'
"name TEXT $0", "write -tests"
// Find items starting with 'wri-' using '*'
"name TEXT $0", "wri*"

全文搜索 (FTS) 索引支持:

  • 词汇单元(token)不区分变音符号和大小写。

  • 词汇单元只能包含 ASCII 和 Latin-1 补充(西方语言)中的字符。所有其他字符均被视为空格。

  • 由连字符 (-) 拆分的单词将拆分为两个词元。例如,full-text 拆分为 fulltext

您可以使用geoWithin操作符查询地理空间数据。 geoWithin操作符获取自定义嵌入式对象的coordinates属性中的纬度/经度对和地理空间形状。 该操作符检查cordinates点是否包含在地理空间形状内。

支持查询以下地理空间形状:

  • GeoCircle

  • GeoBox

  • GeoPolygon

查询地理空间数据:

  1. 创建一个对象,其属性包含嵌入式地理空间数据。

  2. 定义地理空间形状以设置查询边界。

  3. 使用 geoWithin RQL 操作符进行查询。

在以下查询中,我们检查嵌入式location属性的坐标是否包含在GeoCircle形状smallCircle中:

"location geoWithin $0", smallCircle

有关使用嵌入式地理空间数据定义地理空间形状和对象的更多信息,请参阅您的 SDK 的地理空间文档:

反向链接是一种逆向关系链接,可用于查找引用另一个对象的对象。反向链接使用您在对象模式中定义的一对一和一对多关系,但方向相反。在模式中定义的每种关系都隐式具有相应的反向链接。

您可以使用 @links.<ObjectType>.<PropertyName> 语法访问查询中的反向链接,其中 <ObjectType><PropertyName> 是指对象类型上引用所查询对象类型的特定属性。

// Find items that belong to a project with a quota greater than 10 (@links)
"@links.Project.items.quota > 10"

您还可以定义一个linkingObjects属性,以在数据模型中显式包含反向链接。 这样,您就可以使用标准点表示法通过分配的属性名称来引用反向链接。

// Find items that belong to a project with a quota greater than 10 (LinkingObjects)
"projects.quota > 10"

反向链接的结果被视为一个集合,并支持集合操作符。

// Find items where any project that references the item has a quota greater than 0
"ANY @links.Project.items.quota > 0"
// Find items where all projects that reference the item have a quota greater than 0
"ALL @links.Project.items.quota > 0"

您可以在反向链接集合上使用聚合操作符

// 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"

您可以直接在 @links 上使用 @count 操作符来查询指向对象的所有关系的计数。

// Find items that are not referenced by another object of any type
"@links.@count == 0"

使用 SUBQUERY() 谓词函数通过另一个查询来遍历列表属性。

子查询对于以下场景很有用:

  • 在多个条件下匹配列表属性中的每个对象

  • 计算与子查询匹配的对象数量

SUBQUERY() 具有以下结构:

SUBQUERY(<collection>, <variableName>, <predicate>)
  • collection:要遍历的属性的名称

  • variableName:要在子查询中使用的元素的变量名称

  • predicate:子查询谓词。使用 variableName 指定的变量来引用当前遍历的元素。

子查询遍历给定的集合,并针对集合中的每个对象检查给定的谓词。谓词可以引用当前遍历的对象,并将变量名称传递给 SUBQUERY()

子查询表达式解析为对象列表。Realm 仅支持对子查询结果使用 @count 聚合操作符。这样就可以计算子查询输入集合中有多少个对象与谓词匹配。

您可以像使用有效表达式中的任何其他数字一样来使用子查询结果的计数。特别是,您可以将计数与数字 0 进行比较以返回所有匹配的对象。

例子

以下示例显示了项目集合上的两个子查询过滤器。

// Returns projects with items that have not been completed
// by a user named Alex.
"SUBQUERY(items, $item, $item.isComplete == false AND $item.assignee == 'Alex').@count > 0"
// Returns the projects where the number of completed items is
// greater than or equal to the value of a project's `quota` property.
"SUBQUERY(items, $item, $item.isComplete == true).@count >= quota"

使用另一些操作符对查询结果集合进行排序和限制。

Operator
说明
SORT

指定要比较的属性的名称,以及是按升序 (ASC) 还是降序 (DESC) 排序。如果指定多个 SORT 字段,则必须为每个字段指定排序顺序。如果使用多个排序字段,查询会先按第一个字段进行排序,然后再按第二个字段进行排序。

例如,如果使用 SORT (priority DESC, name DESC),则查询将按优先级进行排序,如果优先级值相同,则按名称进行排序。

DISTINCT
指定要比较的属性的名称。在结果集合中删除该属性的重复项。如果指定多个 DISTINCT 字段,查询将删除第一个字段的重复项,然后删除第二个字段的重复项。例如,如果使用 DISTINCT (name, assignee),则查询只会删除两个属性值均相同的重复项。
LIMIT
将结果集合限制为指定数量。

例子

使用查询引擎的排序、去重和限制操作符查找指派给 Ali 的待办事项:

  • 按优先级降序排序

  • 按名称强制实施唯一性

  • 将结果限制为 5 个列项

"assignee == 'Ali' SORT(priority DESC) DISTINCT(name) LIMIT(5)"

向应用添加索引可查询字段可以提高对强分区数据进行简单查询的性能。 例如,如果查询将数据强映射到设备、商店或用户的应用(例如user_id == $0, “641374b03725038381d2e1fb” ,则非常适合使用索引可查询字段。 但是,在查询订阅中使用索引化可查询字段有特定的要求:

  • 每个订阅查询中都必须使用索引化可查询字段。查询中不能缺少该字段。

  • 在订阅查询中,索引化可查询字段必须使用 ==IN 进行至少一次针对常量的比较。例如,user_id == $0, "641374b03725038381d2e1fb"store_id IN $0, {1,2,3}

可以选择包含 AND 比较,前提是使用 ==IN 将索引化可查询字段直接与常量进行至少一次比较。例如,store_id IN {1,2,3} AND region=="Northeast"store_id == 1 AND (active_promotions < 5 OR num_employees < 10)

对索引化可查询字段的无效灵活同步查询包括以下情况的查询:

  • 索引化可查询字段未将 AND 与查询的其余部分结合使用。例如,store_id IN {1,2,3} OR region=="Northeast" 是无效的,因为它使用了 OR 而不是 AND。同样,store_id == 1 AND active_promotions < 5 OR num_employees < 10 也是无效的,因为 AND 仅适用于其旁边的词,而不适用于整个查询。

  • 索引化可查询字段未在相等运算符中使用。例如,store_id > 2 AND region=="Northeast" 是无效的,因为它仅将 > 运算符与索引化可查询字段结合使用,而没有相等比较。

  • 查询中完全没有索引化可查询字段。例如,region=="Northeasttruepredicate 都是无效的,因为它们不含索引化可查询字段。

使用 RQL 操作符时,Flexible Sync有一些限制。当您编写确定要同步哪些数据的查询订阅时,服务器不支持这些查询操作符。但是,您仍然可以使用全部的 RQL 功能来查询客户端应用中的同步数据集。

运算符类型
不支持的运算符
聚合操作符
@avg, @count , @max , @min , @sum
查询后缀
DISTINCT, SORT , LIMIT

不区分大小写的查询 ([c]) 无法有效地使用索引。因此,不建议使用不区分大小写的查询,因为它们可能会导致性能问题。

灵活同步仅支持数组字段的 @count

灵活同步支持使用 IN 运算符来查询列表。

可以查询常量列表,查看其中是否包含可查询字段的值:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

如果某个可查询字段具有数组值,则可以通过查询确定其中是否包含常量值:

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

警告

无法在灵活同步查询中相互比较两个列表。请注意,这是灵活同步查询之外的有效 Realm 查询语言语法。

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

灵活同步不支持查询嵌入式对象或链接中的属性。例如,obj1.field == "foo"

订阅设立任何给定查询订阅的大小限制256 kB 。 超过此限制会导致LimitsExceeded 错误。

后退

修改模式