
以前,我发布了一篇关于Isar的基础文章。
这次,我将更详细地介绍Isar的类定义和数据操作方法。希望对你的开发有所帮助!
准备工作
使用Isar时,需要进行以下准备工作。
配置pubspec.yaml
// 请添加以下包。
dependencies:
isar:
isar_flutter_libs:
dev_dependencies:
build_runner:
isar_generator:
创建Isar实例
import 'package:flutter/material.dart';
import 'package:isar/isar.dart';
import 'package:path_provider/path_provider.dart';
// 如果使用Riverpod
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// 自己创建的Isar提供者的存储位置
import 'package:myApp/email_repository.dart';
// 在main函数中创建
Future<void> main() async {
// 指定本地数据库的保存位置
final dir = await getApplicationSupportDirectory();
// 创建Isar实例
final isar = await Isar.open([EmailSchema], directory: dir.path);
// 创建Isar实例
runApp(ProviderScope(
overrides: [
emailIsarProvider.overrideWithValue(isar),
],
child: const MyApp(),
));
// 参考)使用多个集合时
Future<void> main() async {
// 指定本地数据库的保存位置
final dir = await getApplicationSupportDirectory();
// 创建Isar实例
final isar = await Isar.open([UserSchema, EmailSchema], directory: dir.path);
// 创建Isar实例
runApp(ProviderScope(
overrides: [
userIsarProvider.overrideWithValue(isar),
emailIsarProvider.overrideWithValue(isar),
],
child: const MyApp(),
));
}
定义集合
在NoSQL中,数据以集合和文档的形式管理。与关系型数据库相比,关系如下。
表 : 集合
记录 : 文档
要定义Isar的集合,需要将数据结构定义为类。
基本集合定义
在Isar中,数据类使用@collection注解进行定义。以下是定义一个名为Email的集合的示例。
@collection
class Email {
Email {
Id? id;
required title;
required updatedAt;
}
Id? id;
final String title;
@Index() // 使用“@Index()”为下面的字段创建索引
final DateTime updatedAt;
}
此类具有id、title和updatedAt三个字段。id字段用于唯一标识数据库中的每个条目。
id在Isar中会自动生成。当你将title和updatedAt添加到IsarDB时,id会自动生成。
实际存储的数据图像:
{
"id": 1234, // 自动生成的id
"title": "How to use Isar!!"
"updatedAt": yyyy-mm-dd hh:mm
}
层次集合定义
有时,你可能需要将文档结构化为层次数据结构。这时可以使用@embedded注解定义子类。
@collection
class Email {
Email {
Id? id;
required title;
required updatedAt;
required recipient;
}
Id? id;
final String title;
@Index()
final DateTime updatedAt;
final Recipient? recipient;
}
@embedded
class Recipient {
String? name;
String? address;
}
在这个结构中,Recipient类被嵌入到Email类中。
数据图像:
{
"id": 99999,
"title": "How to use Isar!!",
"recipient": {
"name": "John Doe",
"address": "john.doe@gmail.com"
}
}
编写CRUD查询
接下来是使用Isar进行CRUD操作。
单个数据的插入和更新
要将新数据添加到数据库,需从集合定义中创建实例并将其保存到数据库。使用”put“方法。如果存在相同id的数据,则更新;如果不存在,则插入。
final Isar _isar; // 以下省略
final email = Email()
..title = "How to use Isar CRUD!!"
..recipient = Recipient()
..name = "Jane Doe"
..address = "jane.doe@gmail
.com";
await _isar.emails.put(email);
//emails是在生成文件(在本例中为email_dto.g.dart)中定义的集合类
多个数据的插入和更新
通常在处理多个数据时,使用writeTxn方法进行事务处理。插入或更新多个数据时,使用”putAll“方法。
await isar.writeTxn(() async {
await isar.emails.putAll([email1, email2]);
});
删除单个数据
要删除数据,请指定要删除数据的id。使用”delete“方法。
await isar.emails.delete(emailId);
删除多个数据
要删除符合条件的多个数据,使用”deleteAll“方法。
await isar.emails.delete(emailId);
编写搜索查询
接下来介绍一些在数据库中搜索数据时的方便方法。
Where子句
要查找满足特定条件的数据,使用”where“方法。但where只能用于具有索引(带有@Index()注解)的字段。
使用where时,在”where()”和”findAll()”之间添加条件。
// 查找updatedAt为指定时间的文档
final results = isar.emails
.where()
.updatedAtEqualTo("2024-12-31 23:59")
.findAll();
Where子句中可以使用以下条件。
查询(以字段title为例) | 功能 |
---|---|
.titleEqualTo(“Title Name”) | 匹配等于”Title Name”的值 |
.titleBetween(“T”, “Title Name”) | 匹配在”T”(lower) 和”Title Name”(upper)之间的值 |
.titleGreaterThan(“Title Name”) | 匹配大于”Title Name”的值 |
.titleLessThan(“Title Name”) | 匹配小于”Title Name”的值。默认包含null值 |
使用Filter子句
要设置更复杂的条件,使用”filter“方法。filter可以用于没有索引的字段,但速度比where慢。(可能因为先获取数据再进行筛选)
使用filter时,在”filter()”和”findAll()”之间添加条件。
// 查找以"How"开头(不区分大小写)的文档
final filteredResults = isar.emails
.filter()
.titleStartsWith("How", caseSensitive: false)
.findAll();
其他条件
除了上面的条件,还可以使用其他各种条件进行搜索。这些条件在~.g.dart文件中创建。
查询(以字段title为例) | 功能 |
---|---|
.titleEqualTo(“Title Name”) | 匹配等于”Title Name”的值 |
.titleBetween(“T”, “Title Name”) | 匹配在”T”(lower) 和”Title Name”(upper)之间的值 |
.titleGreaterThan(“Title Name”) | 匹配大于”Title Name”的值 |
.titleLessThan(“Title Name”) | 匹配小于”Title Name”的值。默认包含null值 |
.titleIsNull() | 匹配null值 |
.titleIsNotNull() | 匹配非null值 |
.titleLengthGreaterThan(5) | 匹配长度大于5的值 |
And和Or等逻辑运算符
可以使用And和Or指定多个条件。
// 查找以"How"开头并且updatedAt为指定时间的文档
final filteredResults = isar.emails
.filter()
.titleStartsWith("How")
.and()
.updatedAtEqualTo("2024-12-31 23:59")
.findAll();
还可以使用其他常见的SQL运算符。
查询(以字段title为例) | 功能 |
---|---|
.and() | and(前后条件都为True时为True) |
.or() | or(前后条件任一为True时为True) |
.xor() | xor(前后条件只有一方为True时为True) |
.not() | not(反转后条件的结果) |
.group() | group(将条件分组) |
组合Where子句和Filter子句
通常会创建组合了Where和Filter的查询。
// 查找title大于"How"且updatedAt不为Null的文档
final filteredResults = isar.emails
.titleGreaterThan("How")
.filter()
.updatedAtIsNotNull()
.findAll();
由于Where的速度更快,应尽可能使用Where筛选目标,再使用Filter指定复杂条件。
Offset和Limit
要根据数据数量而非内容获取部分结果,设置”offset“和”limit“。offset是从开始不获取的数量,limit是获取的数量。
final paginatedResults = isar.emails
.where()
.findAll(offset: 10, limit: 5); // 从第11个开始获取5个
全体搜索
要获取数据库中的所有数据,只使用”findAll“。
final allEmails = await isar.emails
.findAll();
最后
本文介绍了使用Flutter和Isar高效管理数据的基本方法。Isar还有很多便捷的功能,本次未能全部介绍,后续会继续撰写相关文章。
官方网站也有使用方法的说明,请参考!!
https://isar.dev/zh/crud.html