持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
Isar:用于 Futter 可跨平台的超快数据库
官方文档:Home | Isar Database
pub:isar | Dart Package (flutter-io.cn)
本文翻译自:
译时版本:3.0.2
查询
查询是如何查找匹配确定条件的记录,例如:
- 查找所有标星的联系人
- 查找联系人中不同的名
- 删除所有未定义姓的联系人
因为查询是在数据库上执行,不是在 Dart 中执行,所以它们相当快。当你灵活运用索引时,可以更进一步改善查询性能。以下的内容,你会学习到如何编写查询和如何使更高效。
执行顺序
Isar 查询总会按照相同的顺序执行:
- 扫描主索引或次要索引查找对象(应用 Where 子句)
- 过滤对象
- 对结果排序
- 应用取唯一值操作
- 对结果进行 Offset & limit 处理。(移值和限定)
- 返回结果
查询操作
在之前的示例中,我们使用 .findAll() 获取所有匹配的对象。当然这里也有一些其它可用的操作:
| 操作 | 说明 |
|---|---|
.findFirst() | 只获取第一条匹配的对象,无匹配对象返回 null |
.findAll() | 获取所有匹配的对象。 |
.count() | 统计匹配查询的对象数量。 |
.deleteFirst() | 从集合中删除第一个匹配的对象。 |
.deleteAll() | 从集合中删除所有匹配的对象。 |
.build() | 编译查询用于后面再利用。如果想要多次执行查询,这会节省编译查询的成本。 |
属性查询
如果只对单个属性的值感兴趣,可以使用属性查询。 这只需编译普通的查询并选择一个属性:
List<String> models = await isar.shoes.where()
.modelProperty()
.findAll();
List<int> sizes = await isar.shoes.where()
.sizeProperty()
.findAll();
只使用单个属性会节省反序列化的时间。 属性查询也可用于嵌入对象和列表。
聚集
也可以对属性查询的值进行聚集。以下的聚集操作都可用:
| 操作 | 说明 |
|---|---|
.min() | 查找最小值,无匹配(对象)则返回 null 。 |
.max() | 查找最大值,无匹配(对象)则返回 null 。 |
.sum() | 求所有值的合计。 |
.average() | 计算所有值的平均值,如果无匹配(对象)则返回 NaN 。 |
相比查找所有匹配对象并手动进行聚集,使用聚集非常快。
动态查询
该部分很有可能和你无关。不推荐使用动态查询除非你绝对需要(很少有这种情况)。
所有上面的例子使用了 QueryBuilder 和生成的静态扩展方法。
你可能想创建动态查询甚至自定义查询语言(如 Isar Inspector)。
这种情况下,可以使用 buildQuery() 方法:
| 参数 | 说明 |
|---|---|
whereClauses | 查询的 Where 子句。 |
whereDistinct | Where 子句是否要返回无重复唯一值(只对单个 Where 子句有用)。 |
whereSort | 扫描 Where 子句的排序顺序(只对单个 Where 子句有用)。 |
filter | 用于结果的过滤。 |
sortBy | 排序用的属性列表。 |
distinctBy | 去重的属性列表。 |
offset | 结果的偏移。 |
limit | 返回的最大结果数。 |
property | 如果非空,只返回该属性的值。 |
让我们创建一个动态查询:
final shoes = await isar.shoes.buildQuery(
whereClauses: [
WhereClause(
indexName: 'size',
lower: [42],
includeLower: true,
upper: [46],
includeUpper: true,
)
],
filter: FilterGroup.and([
FilterCondition(
type: ConditionType.contains,
property: 'model',
value: 'nike',
caseSensitive: false,
),
FilterGroup.not(
FilterCondition(
type: ConditionType.contains,
property: 'model',
value: 'adidas',
caseSensitive: false,
),
),
]),
sortBy: [
SortProperty(
property: 'model',
sort: Sort.desc,
)
],
offset: 10,
limit: 10,
).findAll();
下面的查询是等同的:
final shoes = await isar.shoes.where()
.sizeBetween(42, 46)
.filter()
.modelContains('nike', caseSensitive: false)
.not()
.modelContains('adidas', caseSensitive: false)
.sortByModelDesc()
.offset(10).limit(10)
.findAll();