Flutter数据库增强插件fts5_simple的使用

Flutter数据库增强插件fts5_simple的使用

pub package

fts5_simple 是一个用于支持中文和拼音搜索的 Flutter 插件包装器,它简单且高效地实现了对 Simple tokenizer 的封装。

平台支持

系统 支持
Windows ✔️
MacOS ✔️
Linux ✔️

示例

请查看以下示例代码以获取更多详细信息:

import 'package:flutter/material.dart';
import 'package:fts5_simple/fts5_simple.dart';
import 'package:sqlite3/sqlite3.dart' hide Row;

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final db = sqlite3.openInMemory();

  final TextEditingController _controller = TextEditingController();

  String? _dashboard;

  bool _enableJieBa = false;

  @override
  void initState() {
    super.initState();
    db.loadSimpleExtension();
    // 创建虚拟表
    db.execute("CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'simple')");
    // 插入一些数据
    db.execute(
        """
insert into t1(x) values
 ('周杰伦 Jay Chou:我已分不清,你是友情还是错过的爱情'), 
('周杰伦 Jay Chou:最美的不是下雨天,是曾与你躲过雨的屋檐'),
 ('I love China! 我爱中国!我是中华人民共和国公民!'),
  ('@English &amp;special _characters."''bacon-&amp;and''-eggs%'),
  ('政府は30日、世界文化遺産への登録を目指す「富士山」(山梨県、静岡県)について、国連教育科学文化機関(ユネスコ)の諮問機関から登録を求める勧告が出たと発表した。構成資産の一つ、三保松原(静岡市)の除外が条件。ユネスコが6月にカンボジアで開く世界遺产委员会が最终决定。勧告が覆った例は少なく、登録されれば国内で17件目の世界遗产になる。'),
  ('서는 안될 정도로 꼭 요긴한 것들 만일까? 살펴볼수록 없어도 좋을 만한 것들이 적지 않다.')
  """);
  }

  @override
  void dispose() {
    db.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('插件示例应用'),
        ),
        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20),
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 16),
                child: TextField(controller: _controller),
              ),
              SwitchListTile(
                value: _enableJieBa,
                onChanged: (value) {
                  setState(() {
                    _enableJieBa = value;
                  });
                },
                title: const Text('启用结巴分词'),
              ),
              TextButton(
                onPressed: () {
                  final queryType =
                      _enableJieBa ? 'jieba_query' : 'simple_query';
                  final ret = db.select(
                      "select rowid as id, simple_highlight(t1, 0, '[', ']') as info from t1 where x match $queryType(?)",
                      [_controller.text]);
                  setState(() {
                    _dashboard = ret.toString();
                  });
                },
                child: const Text('搜索'),
              ),
              if (_dashboard != null)
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  child: Text(
                    _dashboard!,
                    style: const TextStyle(fontSize: 20),
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }
}

代码说明

  1. 导入库:

    import 'package:flutter/material.dart';
    import 'package:fts5_simple/fts5_simple.dart';
    import 'package:sqlite3/sqlite3.dart' hide Row;
    
  2. 创建数据库并加载扩展:

    final db = sqlite3.openInMemory();
    db.loadSimpleExtension();
    
  3. 创建虚拟表:

    db.execute("CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'simple')");
    
  4. 插入数据:

    db.execute(
        """
    insert into t1(x) values
     ('周杰伦 Jay Chou:我已分不清,你是友情还是错过的爱情'), 
     ('周杰伦 Jay Chou:最美的不是下雨天,是曾与你躲过雨的屋檐'),
     ('I love China! 我爱中国!我是中华人民共和国公民!'),
     ('@English &amp;special _characters."''bacon-&amp;and''-eggs%'),
     ('政府は30日、世界文化遺産への登録を目指す「富士山」(山梨県、静岡県)について、国連教育科学文化機関(ユネスコ)の諮問機関から登録を求める勧告が出たと発表した。構成資産の一つ、三保松原(静岡市)の除外が条件。ユネスコが6月にカンボジアで開く世界遺产委员会が最终决定。勧告が覆った例は少なく、登録されれば国内で17件目の世界遗产变成。'),
     ('서는 안될 정도로 꼭 요긴한 것들 만일까? 살펴볼수록 없어도 좋을 만한 것들이 적지 않다.')
    """);
    
  5. 处理用户输入并执行查询:

    TextButton(
      onPressed: () {
        final queryType =
            _enableJieBa ? 'jieba_query' : 'simple_query';
        final ret = db.select(
            "select rowid as id, simple_highlight(t1, 0, '[', ']') as info from t1 where x match $queryType(?)",
            [_controller.text]);
        setState(() {
          _dashboard = ret.toString();
        });
      },
      child: const Text('搜索'),
    ),
    

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

1 回复

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


当然,以下是如何在Flutter项目中使用fts5_simple插件来进行SQLite的全文搜索(FTS5)的示例代码。fts5_simple是一个Flutter插件,它提供了一个简单的接口来使用SQLite的FTS5(Full-Text Search version 5)功能。

首先,确保你的Flutter项目中已经添加了fts5_simple依赖。在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  fts5_simple: ^最新版本号

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

初始化数据库和创建FTS5表

在你的Flutter应用中,你需要初始化数据库并创建一个FTS5表。以下是一个完整的示例代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('FTS5 Simple Example'),
        ),
        body: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Fts5Database db;

  @override
  void initState() {
    super.initState();
    initDatabase();
  }

  Future<void> initDatabase() async {
    // 打开数据库连接
    db = await Fts5Database.openDatabase(
      path: 'my_database.db',
      version: 1,
      onCreate: (Database db, int version) async {
        // 创建一个普通的表
        await db.execute('CREATE TABLE my_table (id INTEGER PRIMARY KEY, content TEXT)');

        // 创建一个FTS5虚拟表
        await db.execute('''
          CREATE VIRTUAL TABLE my_fts_table USING fts5(
            content TEXT,
            content_rowid INTEGER HIDDEN,
            tokenize=porter
          )
        ''');

        // 创建一个触发器,当my_table中的数据插入、更新或删除时,同步更新my_fts_table
        await db.execute('''
          CREATE TRIGGER my_table_after_insert
          AFTER INSERT ON my_table
          FOR EACH ROW BEGIN
            INSERT INTO my_fts_table(rowid, content) VALUES (new.rowid, new.content);
          END;
        ''');

        await db.execute('''
          CREATE TRIGGER my_table_after_update
          AFTER UPDATE ON my_table
          FOR EACH ROW BEGIN
            INSERT INTO my_fts_table(rowid, content) VALUES (new.rowid, new.content);
          END;
        ''');

        await db.execute('''
          CREATE TRIGGER my_table_after_delete
          AFTER DELETE ON my_table
          FOR EACH ROW BEGIN
            DELETE FROM my_fts_table WHERE rowid=old.rowid;
          END;
        ''');
      },
    );
  }

  Future<void> addData(String content) async {
    // 向my_table插入数据,触发器会自动更新my_fts_table
    await db.execute('INSERT INTO my_table(content) VALUES (?)', [content]);
  }

  Future<List<Map<String, dynamic>>> searchData(String query) async {
    // 从my_fts_table进行全文搜索
    List<Map<String, dynamic>> results = await db.rawQuery('SELECT rowid, * FROM my_fts_table WHERE my_fts_table MATCH ?', [query]);
    return results;
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextField(
            decoration: InputDecoration(labelText: 'Enter search query'),
            onSubmitted: (query) async {
              List<Map<String, dynamic>> results = await searchData(query);
              // 处理搜索结果(这里简单打印到控制台)
              print(results);
            },
          ),
          SizedBox(height: 16),
          ElevatedButton(
            onPressed: () async {
              await addData('This is a sample text for full-text search.');
              print('Data added.');
            },
            child: Text('Add Sample Data'),
          ),
        ],
      ),
    );
  }
}

解释

  1. 初始化数据库

    • 使用Fts5Database.openDatabase方法打开或创建数据库。
    • onCreate回调中,创建了一个普通表my_table和一个FTS5虚拟表my_fts_table
    • 创建了三个触发器,确保当my_table中的数据发生变化时,my_fts_table能够同步更新。
  2. 添加数据

    • 使用addData方法向my_table插入数据,由于触发器的存在,my_fts_table会自动更新。
  3. 搜索数据

    • 使用searchData方法进行全文搜索,查询my_fts_table
  4. UI部分

    • 包含一个TextField用于输入搜索查询。
    • 一个ElevatedButton用于添加示例数据。

注意事项

  • 确保你已经正确安装并配置了fts5_simple插件。
  • FTS5的匹配模式和分词器可以根据需要进行配置,这里使用了porter分词器。
  • 上述代码仅作为示例,实际项目中可能需要根据具体需求进行调整和优化。

希望这个示例能够帮助你在Flutter项目中使用fts5_simple插件进行全文搜索。

回到顶部