Flutter 的 sqflite 查询

Flutter's sqflite queries

我正在使用一个已经存在的数据库 dictionary.db,它有一个 table words 并且有 4 列 idenglishWordgermanWord, isFavorite.

我正在尝试使用 Sqflite return 一个基于英语输入的德语单词列表,用户流程几乎是这样工作的:用户输入一个英语单词(示例:"Ability")和我 return 该词的德语同义词列表。

我的问题是我不知道如何使用我正在尝试的方法return获取完整列表,而不仅仅是预期的搜索结果

这是我的实体:

class Word {
  final String id;
  final String eng;
  final String ger;
  final String isFav;

  Word({this.id, this.eng, this.ger, this.isFav});

  Map<String, dynamic> toMap() {
    return {
      'wordId': id,
      'englishWord': eng,
      'germanWord': ger,
      'isFavorite': isFav, 
    };
  }

  factory Word.fromMap(Map<String, dynamic> json) => new Word(
    id: json['wordId'],
    eng: json['englishWord'],
    ger: json['germanWord'],
    isFav: json['isFavorite']
  );
}

这是我的数据库助手class:

class DatabaseHelper{
  DatabaseHelper._();
  static final DatabaseHelper databaseHelper = DatabaseHelper._();
  Database _database;

  static const String DB_NAME = "dict.db";
  static const String TABLE = "words";
  static const String ID = "wordId";
  static const String ENGLISH_WORD = "englishWord";
  static const String GERMAN_WORD = "germanWord";
  static const String IS_FAV = "isFavorite";

  Future<Database> get database async {
    if (_database != null) return _database;
    _database = await getDatabaseInstance();
    return _database;
  }

  Future<Database> getDatabaseInstance() async {
    io.Directory directory = await getApplicationDocumentsDirectory();
    String path = join(directory.path, DB_NAME);
    return await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
          "$ID TEXT,"
          "$ENGLISH_WORD TEXT,"
          "$GERMAN_WORD TEXT,"
          "$IS_FAV TEXT"
          ")");
    });
  }

  //This is where I get the search result list
  //I am stuck here I don't know where to go from here, I only get the full list
  Future<List<Word>> searchEnglishResults(String userSearch) async{
    final db = await database;
    var response = await db.query("Word");
    List<Word> list = response.map((c) => Word.fromMap(c)).toList();
    return list;
  }

我假设数据库如下所示:

|id     | englidhWord | germanWord        | isFavorite |
|-------|-------------|-------------------|------------|
| 'id0' | 'bye'       | 'Tschüss'         | 'false'    |
| 'id1' | 'bye'       | 'Auf Wiedersehen' | 'true'     |

所以如果用户搜索 "bye",she/he 应该会收到 ['Tschüss','Auf Wiedersehen'](Word 模型不仅是德语单词)。

为此,query 有一些选项,例如 wherewhereArgs,您可以使用它们来搜索数据库中的特定行。

此处我们要在数据库中搜索其 englidhWord 字段值为 bye 的行。

这是您的数据库的编辑版本:

import 'dart:io';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sudoku/src/word.dart';

class DatabaseHelper {
  DatabaseHelper._();
  static final DatabaseHelper databaseHelper = DatabaseHelper._();
  Database _database;

  String DB_NAME = "dict.db";
  static const String TABLE = "words";
  static const String ID = "wordId";
  static const String ENGLISH_WORD = "englishWord";
  static const String GERMAN_WORD = "germanWord";
  static const String IS_FAV = "isFavorite";

  Future<Database> get database async {
    if (_database != null) return _database;
    _database = await getDatabaseInstance();
    return _database;
  }

  Future<Database> getDatabaseInstance() async {
    Directory directory = await getApplicationDocumentsDirectory();
    String path = join(directory.path, DB_NAME);
    return await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
          "$ID TEXT,"
          "$ENGLISH_WORD TEXT,"
          "$GERMAN_WORD TEXT,"
          "$IS_FAV TEXT"
          ")");
    });
  }
   //add new words
   Future<int> add(Word word) async {
    final db = await database;
    var response = await db.insert(TABLE, word.toMap());

    return response;
  }

  //This is where I get the search result list
  //I am stuck here I don't know where to go from here, I only get the full list
  Future<List<Word>> searchEnglishResults(String userSearch) async {
    final db = await database;
    var response = await db
        .query(TABLE, where: '$ENGLISH_WORD = ?', whereArgs: [userSearch]);
    List<Word> list = response.map((c) => Word.fromMap(c)).toList();
    return list;
  }
}

然后我在名为 MyApp

的页面上使用列表视图显示结果
import 'package:flutter/material.dart';
import 'package:sudoku/src/db.dart';
import 'package:sudoku/src/word.dart';

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

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  DatabaseHelper db;
  @override
  void initState() {
    db = DatabaseHelper.databaseHelper;
    add();
    super.initState();
  }

  add() async {
    // await db.add(Word(eng: 'hi', ger: 'Hallo', id: 'id2', isFav: 'true'));
    // await db.add(Word(eng: 'bye', ger: 'Tschüss', id: 'id0', isFav: 'fasle'));
    // await db.add(
    //     Word(eng: 'bye', ger: 'Auf Wiedersehen', id: 'id0', isFav: 'true'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: FutureBuilder<List<Word>>(
        future: db.searchEnglishResults('bye'),
        builder: (BuildContext context, AsyncSnapshot<List<Word>> snapshot) {
          if (snapshot.hasData)
            return ListView.builder(
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  title: Text(snapshot.data[index].ger),
                  subtitle: Text(snapshot.data[index].eng),
                  trailing: Text(snapshot.data[index].isFav),
                );
              },
              itemCount: snapshot.data.length,
            );

          return Center(
            child: CircularProgressIndicator(),
          );
        },
      ),
    );
  }
}

我在数据库和 MyApp 的 initState 中包含了一个名为 "add" 的函数,用于向数据库添加新词。

如果你多次刷新应用程序,它会添加重复的行,原因是你应该使数据库字段之一唯一,这里可以id这样做你应该创建table 如下所示:

return await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
          "$ID TEXT NOT NULL PRIMARY KEY,"
          "$ENGLISH_WORD TEXT,"
          "$GERMAN_WORD TEXT,"
          "$IS_FAV TEXT"
          ")");
    });

还有DB中的add函数,你应该选择当它面对一个重复的行(这里是Word)时应该做什么,有一些选项,一个可以是替换它,它应该改变像这样:

  //add new words
  Future<int> add(Word word) async {
    final db = await database;
    var response = await db.insert(TABLE, word.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);

    return response;
  }

我希望这就是您要找的东西。