Flutter数据库管理插件nest_db的使用

Flutter数据库管理插件nest_db的使用

Nest DB

Beta版本

Nest DB 是一个专为 Flutter 应用设计的轻量级内存数据库,具有持久化存储功能。它提供了一种简单而强大的方式来管理应用程序中的结构化数据,支持模式验证、响应式更新和持久化存储。

特性

  • 文档导向: 将数据存储为类似 JSON 的文档(映射)集合,提供了灵活性和易用性。
  • 模式验证: 允许定义集合的模式以确保数据符合特定的数据类型和规则。
  • 响应式更新: 集成到 Flutter 的响应式框架中,可以轻松监听数据变化并相应地更新用户界面。
  • 持久化存储: 将数据保存到磁盘,确保在应用会话之间保持数据持久性。每个集合的数据都存储在单独的 JSON 文件中。
  • 多集合支持: 支持在一个 Nest 数据库实例中管理多个独立的集合。
  • 可选加密: 提供可选的数据加密以增强安全性。
  • 简单的 API: 提供直观的 API 进行 CRUD(创建、读取、更新、删除)操作以及更高级的查询。

开始使用

1. 安装

pubspec.yaml 中添加 nest_db 依赖:

dependencies:
  nest_db: <最新版本>

2. 导入

在 Dart 文件中导入 nest_db 包:

import 'package:nest_db/nest_db.dart';

3. 初始化

在使用之前初始化 Nest DB,最好在主函数中进行初始化:

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); // 确保 Flutter 已初始化
  final db = Nest();
  await db.initialize('your_encryption_key'); // 可选的加密密钥
  runApp(MyApp());
}

如果不需要加密,可以传递空字符串:

await db.initialize(''); // 无加密

4. 创建集合和定义模式

创建集合并定义模式以强制执行数据结构。模式是可选的,但强烈推荐用于数据完整性。

final userSchema = Schema({
  'id': FieldType(type: String, isRequired: true),
  'name': FieldType(type: String),
  'age': FieldType(type: int),
  'email': FieldType(type: String),
  'address': FieldType(type: Map),
});

await db.createCollection('users', userSchema);

5. 执行 CRUD 操作

获取特定集合的 CollectionManager 实例:

final usersCollection = db.getCollection('users');
final productsCollection = db.getCollection('products');

if (usersCollection == null || productsCollection == null) {
  // 处理集合不存在的情况
  return;
}

创建(写入)

await usersCollection.write('1', {
  id: '1',
  name: 'Alice',
  age: 30,
  email: 'alice@example.com',
  address: {
    street: {
      name: "Main St",
      number: 123
    },
    city: "New York"
  }
});

读取

final user = await usersCollection.read('1');
print(user?.data); 

// 输出:
{
  id: "1",
  name: "Alice",
  age: 30,
  email: "alice@example.com",
  createdAt: ..., // 实际日期对象
  updatedAt: ...  // 实际日期对象
}

更新

await usersCollection.update('1', {
  age: 31,
  email: '[email address removed]',
  address: {
    street: {
      name: "Main St",
      number: 124
    },
    city: "New York"
  }
});

删除

await usersCollection.delete('your-doc-id');

6. 高级查询

投影

仅检索文档中的特定字段:

final documents = {
  "1": {"name": "Alice", "age": 25, "city": "New York"},
  "2": {"name": "Bob", "occupation": "Software Engineer"},
  "3": {"name": "Charlie", "age": 30}, // 缺少 "city" 字段
};
final schema = Schema({}); // 假模式
final collectionManager = CollectionManager('users', documents, schema);

// 仅投影 "name" 和 "age" 字段
final nameAgeProjections = collectionManager.project(fields: ["name", "age"]);
print(nameAgeProjections);
// 输出:
[
  {"id": "1", "name": "Alice", "age": 25},
  {"id": "2", "name": "Bob"}, // 缺少 "age" 字段
  {"id": "3", "name": "Charlie", "age": 30},
]

// 仅投影 "name" 字段
final nameProjections = collectionManager.project(fields: ["name"]);
print(nameProjections);
// 输出:
[
  {"id": "1", "name": "Alice"},
  {"id": "2", "name": "Bob"},
  {"id": "3", "name": "Charlie"},
]

存在查询

检查字段是否存在于文档中:

final documents = {
  "1": {"name": "Alice", "age": 25},
  "2": {"name": "Bob"}, // 缺少 "age" 字段
  "3": {"name": "Charlie", "age": 30},
};
final schema = Schema({}); // 假模式
final collectionManager = CollectionManager('users', documents, schema);

// 查找包含 "age" 字段的用户
final withAge = collectionManager.existsQuery("age");
print(withAge);

// 输出:
[{"name": "Alice", "age": 25}, {"name": "Charlie", "age": 30}]

// 查找不包含 "age" 字段的用户
final withoutAge = collectionManager.existsQuery("age", exists: false);
print(withoutAge);

// 输出:
[{"name": "Bob"}]

// 查找包含 "city" 字段的用户
final withCity = collectionManager.existsQuery("city");
print(withCity);

// 输出:
[]

通配符查询

搜索字段匹配通配符模式的文档:

final documents = {
  "1": {"name": "Alice Wonderland"},
  "2": {"name": "Bob the Builder"},
  "3": {"name": "Charlie Chaplin"},
  "4": {"name": "David"},
  "5": {"name": null},
};
final schema = Schema({}); // 假模式
final collectionManager = CollectionManager('users', documents, schema);

// 查找名字以 "A" 开头的用户
final startsWithA = collectionManager.wildcardQuery("name", "A*");
print(startsWithA);

// 输出:
[{"name": "Alice Wonderland"}]

// 查找名字以 "er" 结尾的用户
final endsWithEr = collectionManager.wildcardQuery("name", "*er");
print(endsWithEr);

// 输出:
[{"name": "Bob the Builder"}]

// 查找名字包含 "li" 的用户
final containsLi = collectionManager.wildcardQuery("name", "*li*");
print(containsLi);

// 输出:
[{"name": "Alice Wonderland"}, {"name": "Charlie Chaplin"}]

// 查找所有名字
final allNames = collectionManager.wildcardQuery("name", "*");
print(allNames);

// 输出:
[
  {"name": "Alice Wonderland"},
  {"name": "Bob the Builder"},
  {"name": "Charlie Chaplin"},
  {"name": "David"},
  {"name": null}
]

// 查找名字为 null 的用户
final nullName = collectionManager.wildcardQuery("name", "");
print(nullName);

// 输出:
[{"name": null}]

嵌套字段查询

基于嵌套对象中的值查询文档:

final documents = {
  "1": {
    "address": {
      "street": {"name": "Main St", "number": 123},
      "city": "New York"
    }
  },
  "2": {
    "address": {
      "street": {"name": "Oak Ave", "number": 456},
      "city": "Los Angeles"
    }
  },
  "3": {"address": {"city": "Chicago"}}, // 缺少 "street"
  "4": {"name": "David"}, // 缺少 "address"
};
final schema = Schema({}); // 假模式
final collectionManager = CollectionManager('places', documents, schema);

// 查找位于 "Main St" 的地方
final mainStreetPlaces = collectionManager.nestedFieldQuery("address.street.name", "Main St");
print(mainStreetPlaces);

// 输出:
[{"address": {"street": {"name": "Main St", "number": 123}, "city": "New York"}}]

// 查找街道号为 456 的地方
final number456Places = collectionManager.nestedFieldQuery("address.street.number", 456);
print(number456Places);

// 输出:
[{"address": {"street": {"name": "Oak Ave", "number": 456}, "city": "Los Angeles"}}]

// 查找名字为 David 的地方
final davidPlaces = collectionManager.nestedFieldQuery("name", "David");
print(davidPlaces);

// 输出:
[{"name": "David"}]

响应式更新

监听集合的变化:

db.watchCollection('users').listen((change) {
  print('Users collection changed: $change');
});

更多关于Flutter数据库管理插件nest_db的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据库管理插件nest_db的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用nest_db插件进行数据库管理的示例代码。nest_db是一个轻量级的Flutter数据库管理插件,支持简单的CRUD(创建、读取、更新、删除)操作。

首先,确保你已经在pubspec.yaml文件中添加了nest_db依赖:

dependencies:
  flutter:
    sdk: flutter
  nest_db: ^最新版本号  # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖。

接下来,我们编写一个示例代码来展示如何使用nest_db进行数据库操作。

示例代码

import 'package:flutter/material.dart';
import 'package:nest_db/nest_db.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Nest DB Example'),
        ),
        body: Center(
          child: NestDBExample(),
        ),
      ),
    );
  }
}

class NestDBExample extends StatefulWidget {
  @override
  _NestDBExampleState createState() => _NestDBExampleState();
}

class _NestDBExampleState extends State<NestDBExample> {
  NestDB? _db;

  @override
  void initState() {
    super.initState();
    // 初始化数据库,指定数据库名称和版本号
    _db = NestDB(
      databaseName: 'example_db',
      version: 1,
    );

    // 打开数据库连接
    _db?.openDatabase()?.then((_) {
      // 创建表(如果表不存在)
      _createTable();
    });
  }

  @override
  void dispose() {
    // 关闭数据库连接
    _db?.close();
    super.dispose();
  }

  Future<void> _createTable() async {
    // 定义表结构
    String createTableQuery = '''
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        age INTEGER NOT NULL
      )
    ''';

    // 执行创建表操作
    await _db?.execute(createTableQuery);
  }

  Future<void> _insertData() async {
    // 插入数据
    String insertQuery = "INSERT INTO users (name, age) VALUES (?, ?)";
    await _db?.rawInsert(insertQuery, ['Alice', 30]);
    await _db?.rawInsert(insertQuery, ['Bob', 25]);
  }

  Future<List<Map<String, dynamic>>> _queryData() async {
    // 查询数据
    String query = "SELECT * FROM users";
    return await _db?.rawQuery(query);
  }

  Future<void> _updateData() async {
    // 更新数据
    String updateQuery = "UPDATE users SET age = ? WHERE name = ?";
    await _db?.rawUpdate(updateQuery, [26, 'Bob']);
  }

  Future<void> _deleteData() async {
    // 删除数据
    String deleteQuery = "DELETE FROM users WHERE name = ?";
    await _db?.rawDelete(deleteQuery, ['Alice']);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        ElevatedButton(
          onPressed: () async {
            await _insertData();
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Data inserted')));
          },
          child: Text('Insert Data'),
        ),
        ElevatedButton(
          onPressed: () async {
            List<Map<String, dynamic>> users = await _queryData();
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text('Query Result: ${users.map((e) => e['name']).join(', ')}'),
              ),
            );
          },
          child: Text('Query Data'),
        ),
        ElevatedButton(
          onPressed: () async {
            await _updateData();
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Data updated')));
          },
          child: Text('Update Data'),
        ),
        ElevatedButton(
          onPressed: () async {
            await _deleteData();
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Data deleted')));
          },
          child: Text('Delete Data'),
        ),
      ],
    );
  }
}

说明

  1. 初始化数据库:在initState方法中,我们初始化了NestDB实例并打开数据库连接。
  2. 创建表:在_createTable方法中,我们定义了表结构并创建表。
  3. 插入数据:在_insertData方法中,我们向表中插入数据。
  4. 查询数据:在_queryData方法中,我们查询表中的数据并返回结果。
  5. 更新数据:在_updateData方法中,我们更新表中的数据。
  6. 删除数据:在_deleteData方法中,我们删除表中的数据。

这个示例展示了如何使用nest_db插件进行基本的数据库操作。你可以根据需要扩展这个示例,添加更多的功能和错误处理。

回到顶部