[官文翻译]Futter超快数据库Isar - 概念 - 查询(下)- 执行顺序 & 查询 & 聚集 & 动态查询

428 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情


Isar:用于 Futter 可跨平台的超快数据库

官方文档:Home | Isar Database

pub:isar | Dart Package (flutter-io.cn)

本文翻译自:

译时版本:3.0.2


查询

查询是如何查找匹配确定条件的记录,例如:

  • 查找所有标星的联系人
  • 查找联系人中不同的名
  • 删除所有未定义姓的联系人

因为查询是在数据库上执行,不是在 Dart 中执行,所以它们相当快。当你灵活运用索引时,可以更进一步改善查询性能。以下的内容,你会学习到如何编写查询和如何使更高效。


执行顺序

Isar 查询总会按照相同的顺序执行:

  1. 扫描主索引或次要索引查找对象(应用 Where 子句)
  2. 过滤对象
  3. 对结果排序
  4. 应用取唯一值操作
  5. 对结果进行 Offset & limit 处理。(移值和限定)
  6. 返回结果

查询操作

在之前的示例中,我们使用 .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 子句。
whereDistinctWhere 子句是否要返回无重复唯一值(只对单个 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();