lib/search/word_search: split

This commit is contained in:
2025-05-16 17:06:00 +02:00
parent 6c580e95e2
commit 9d9ce840fa
5 changed files with 444 additions and 357 deletions

View File

@@ -1,7 +1,7 @@
import 'package:jadb/models/word_search/word_search_result.dart';
import 'package:jadb/models/kanji_search/kanji_search_result.dart';
import 'package:jadb/models/radkfile/radicals_search_result.dart';
import 'package:jadb/search/word_search.dart';
import 'package:jadb/search/word_search/word_search.dart';
import 'package:jadb/search/kanji_search.dart';

View File

@@ -0,0 +1,292 @@
import 'package:jadb/util/sqlite_utils.dart';
import 'package:sqflite_common/sqflite.dart';
class LinearWordQueryData {
final List<Map<String, Object?>> senses;
final List<Map<String, Object?>> readingElements;
final List<Map<String, Object?>> kanjiElements;
final List<Map<String, Object?>> jlptTags;
final List<Map<String, Object?>> commonEntries;
final List<Map<String, Object?>> senseAntonyms;
final List<Map<String, Object?>> senseDialects;
final List<Map<String, Object?>> senseFields;
final List<Map<String, Object?>> senseGlossaries;
final List<Map<String, Object?>> senseInfos;
final List<Map<String, Object?>> senseLanguageSources;
final List<Map<String, Object?>> senseMiscs;
final List<Map<String, Object?>> sensePOSs;
final List<Map<String, Object?>> senseRestrictedToKanjis;
final List<Map<String, Object?>> senseRestrictedToReadings;
final List<Map<String, Object?>> senseSeeAlsos;
final List<Map<String, Object?>> exampleSentences;
final List<Map<String, Object?>> readingElementInfos;
final List<Map<String, Object?>> readingElementRestrictions;
final List<Map<String, Object?>> kanjiElementInfos;
const LinearWordQueryData({
required this.senses,
required this.readingElements,
required this.kanjiElements,
required this.jlptTags,
required this.commonEntries,
required this.senseAntonyms,
required this.senseDialects,
required this.senseFields,
required this.senseGlossaries,
required this.senseInfos,
required this.senseLanguageSources,
required this.senseMiscs,
required this.sensePOSs,
required this.senseRestrictedToKanjis,
required this.senseRestrictedToReadings,
required this.senseSeeAlsos,
required this.exampleSentences,
required this.readingElementInfos,
required this.readingElementRestrictions,
required this.kanjiElementInfos,
});
}
Future<LinearWordQueryData> fetchLinearWordQueryData(
DatabaseExecutor connection,
List<int> entryIds,
) async {
late final List<Map<String, Object?>> senses;
final Future<List<Map<String, Object?>>> senses_query = connection.query(
'JMdict_Sense',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> readingElements;
final Future<List<Map<String, Object?>>> readingElements_query =
connection.query(
'JMdict_ReadingElement',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> kanjiElements;
final Future<List<Map<String, Object?>>> kanjiElements_query =
connection.query(
'JMdict_KanjiElement',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> jlptTags;
final Future<List<Map<String, Object?>>> jlptTags_query = connection.query(
'JMdict_JLPTTag',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> commonEntries;
final Future<List<Map<String, Object?>>> commonEntries_query =
connection.query(
'JMdict_EntryCommon',
where: 'entryId IN (${entryIds.join(',')})',
);
await Future.wait([
senses_query.then((value) => senses = value),
readingElements_query.then((value) => readingElements = value),
kanjiElements_query.then((value) => kanjiElements = value),
jlptTags_query.then((value) => jlptTags = value),
commonEntries_query.then((value) => commonEntries = value),
]);
// Sense queries
final senseIds = senses.map((sense) => sense['senseId'] as int).toList();
late final List<Map<String, Object?>> senseAntonyms;
final Future<List<Map<String, Object?>>> senseAntonyms_query =
connection.rawQuery("""
SELECT
JMdict_SenseAntonym.senseId,
JMdict_SenseAntonym.ambiguous,
JMdict_SenseAntonym.xrefEntryId,
JMdict_BaseAndFurigana.base,
JMdict_BaseAndFurigana.furigana
FROM JMdict_SenseAntonym
JOIN "JMdict_BaseAndFurigana"
ON JMdict_SenseAntonym.xrefEntryId = JMdict_BaseAndFurigana.entryId
WHERE
senseId IN (${senseIds.join(',')})
AND COALESCE("JMdict_BaseAndFurigana"."kanjiOrderNum", 1)
+ "JMdict_BaseAndFurigana"."readingOrderNum"
= 2
ORDER BY
JMdict_SenseAntonym.senseId,
JMdict_SenseAntonym.xrefEntryId
""");
late final List<Map<String, Object?>> senseDialects;
final Future<List<Map<String, Object?>>> senseDialects_query =
connection.query(
'JMdict_SenseDialect',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseFields;
final Future<List<Map<String, Object?>>> senseFields_query = connection.query(
'JMdict_SenseField',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseGlossaries;
final Future<List<Map<String, Object?>>> senseGlossaries_query =
connection.query(
'JMdict_SenseGlossary',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseInfos;
final Future<List<Map<String, Object?>>> senseInfos_query = connection.query(
'JMdict_SenseInfo',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseLanguageSources;
final Future<List<Map<String, Object?>>> senseLanguageSources_query =
connection.query(
'JMdict_SenseLanguageSource',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseMiscs;
final Future<List<Map<String, Object?>>> senseMiscs_query = connection.query(
'JMdict_SenseMisc',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> sensePOSs;
final Future<List<Map<String, Object?>>> sensePOSs_query = connection.query(
'JMdict_SensePOS',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseRestrictedToKanjis;
final Future<List<Map<String, Object?>>> senseRestrictedToKanjis_query =
connection.query(
'JMdict_SenseRestrictedToKanji',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseRestrictedToReadings;
final Future<List<Map<String, Object?>>> senseRestrictedToReadings_query =
connection.query(
'JMdict_SenseRestrictedToReading',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseSeeAlsos;
final Future<List<Map<String, Object?>>> senseSeeAlsos_query =
connection.rawQuery("""
SELECT
JMdict_SenseSeeAlso.senseId,
JMdict_SenseSeeAlso.ambiguous,
JMdict_SenseSeeAlso.xrefEntryId,
JMdict_BaseAndFurigana.base,
JMdict_BaseAndFurigana.furigana
FROM JMdict_SenseSeeAlso
JOIN "JMdict_BaseAndFurigana"
ON JMdict_SenseSeeAlso.xrefEntryId = JMdict_BaseAndFurigana.entryId
WHERE
senseId IN (${senseIds.join(',')})
AND COALESCE("JMdict_BaseAndFurigana"."kanjiOrderNum", 1)
+ "JMdict_BaseAndFurigana"."readingOrderNum"
= 2
ORDER BY
JMdict_SenseSeeAlso.senseId,
JMdict_SenseSeeAlso.xrefEntryId
""");
late final List<Map<String, Object?>> exampleSentences;
final Future<List<Map<String, Object?>>> exampleSentences_query =
connection.query(
'JMdict_ExampleSentence',
where: 'senseId IN (${senseIds.join(',')})',
);
// Reading queries
final readingIds = readingElements
.map((element) => (
element['entryId'] as int,
escapeStringValue(element['reading'] as String)
))
.toList();
late final List<Map<String, Object?>> readingElementInfos;
final Future<List<Map<String, Object?>>> readingElementInfos_query =
connection.query(
'JMdict_ReadingElementInfo',
where: '(entryId, reading) IN (${readingIds.join(',')})',
);
late final List<Map<String, Object?>> readingElementRestrictions;
final Future<List<Map<String, Object?>>> readingElementRestrictions_query =
connection.query(
'JMdict_ReadingElementRestriction',
where: '(entryId, reading) IN (${readingIds.join(',')})',
);
// Kanji queries
final kanjiIds = kanjiElements
.map((element) => (
element['entryId'] as int,
escapeStringValue(element['reading'] as String)
))
.toList();
late final List<Map<String, Object?>> kanjiElementInfos;
final Future<List<Map<String, Object?>>> kanjiElementInfos_query =
connection.query(
'JMdict_KanjiElementInfo',
where: '(entryId, reading) IN (${kanjiIds.join(',')})',
);
await Future.wait([
senseAntonyms_query.then((value) => senseAntonyms = value),
senseDialects_query.then((value) => senseDialects = value),
senseFields_query.then((value) => senseFields = value),
senseGlossaries_query.then((value) => senseGlossaries = value),
senseInfos_query.then((value) => senseInfos = value),
senseLanguageSources_query.then((value) => senseLanguageSources = value),
senseMiscs_query.then((value) => senseMiscs = value),
sensePOSs_query.then((value) => sensePOSs = value),
senseRestrictedToKanjis_query
.then((value) => senseRestrictedToKanjis = value),
senseRestrictedToReadings_query
.then((value) => senseRestrictedToReadings = value),
senseSeeAlsos_query.then((value) => senseSeeAlsos = value),
exampleSentences_query.then((value) => exampleSentences = value),
readingElementInfos_query.then((value) => readingElementInfos = value),
readingElementRestrictions_query
.then((value) => readingElementRestrictions = value),
kanjiElementInfos_query.then((value) => kanjiElementInfos = value),
]);
return LinearWordQueryData(
senses: senses,
readingElements: readingElements,
kanjiElements: kanjiElements,
jlptTags: jlptTags,
commonEntries: commonEntries,
senseAntonyms: senseAntonyms,
senseDialects: senseDialects,
senseFields: senseFields,
senseGlossaries: senseGlossaries,
senseInfos: senseInfos,
senseLanguageSources: senseLanguageSources,
senseMiscs: senseMiscs,
sensePOSs: sensePOSs,
senseRestrictedToKanjis: senseRestrictedToKanjis,
senseRestrictedToReadings: senseRestrictedToReadings,
senseSeeAlsos: senseSeeAlsos,
exampleSentences: exampleSentences,
readingElementInfos: readingElementInfos,
readingElementRestrictions: readingElementRestrictions,
kanjiElementInfos: kanjiElementInfos,
);
}

View File

@@ -0,0 +1,72 @@
import 'package:jadb/search/word_search/word_search.dart';
import 'package:jadb/util/text_filtering.dart';
import 'package:sqflite_common/sqlite_api.dart';
SearchMode _determineSearchMode(String word) {
final bool containsKanji = kanjiRegex.hasMatch(word);
final bool containsAscii = RegExp(r'[A-Za-z]').hasMatch(word);
if (containsKanji && containsAscii) {
return SearchMode.MixedKanji;
} else if (containsKanji) {
return SearchMode.Kanji;
} else if (containsAscii) {
return SearchMode.English;
} else if (word.contains(hiraganaRegex) || word.contains(katakanaRegex)) {
return SearchMode.Kana;
} else {
return SearchMode.MixedKana;
}
}
Future<List<int>> fetchEntryIds(
DatabaseExecutor connection,
String word,
SearchMode searchMode,
int pageSize,
int? offset,
) async {
if (searchMode == SearchMode.Auto) {
searchMode = _determineSearchMode(word);
}
assert(
word.isNotEmpty,
'Word should not be empty when fetching entry IDs',
);
late final List<int> entryIds;
if (searchMode == SearchMode.Kanji) {
entryIds = (await connection.query(
'JMdict_EntryByKanji',
where: 'kanji LIKE ?',
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
} else if (searchMode == SearchMode.Kana) {
entryIds = (await connection.query(
'JMdict_EntryByKana',
where: 'kana LIKE ?',
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
} else {
entryIds = (await connection.query(
'JMdict_EntryByEnglish',
where: 'english LIKE ?',
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
}
return entryIds;
}

View File

@@ -12,363 +12,8 @@ import 'package:jadb/models/word_search/word_search_sense.dart';
import 'package:jadb/models/word_search/word_search_sense_language_source.dart';
import 'package:jadb/models/word_search/word_search_sources.dart';
import 'package:jadb/models/word_search/word_search_xref_entry.dart';
import 'package:jadb/util/sqlite_utils.dart';
import 'package:jadb/util/text_filtering.dart';
import 'package:sqflite_common/sqlite_api.dart';
// TODO: Support globs
// TODO: Support tags
// TODO: Prefer original kana type when sorting results
// TODO: Support mixing kana and romaji
enum SearchMode {
Auto,
English,
Kanji,
MixedKanji,
Kana,
MixedKana,
}
SearchMode _determineSearchMode(String word) {
final bool containsKanji = kanjiRegex.hasMatch(word);
final bool containsAscii = RegExp(r'[A-Za-z]').hasMatch(word);
if (containsKanji && containsAscii) {
return SearchMode.MixedKanji;
} else if (containsKanji) {
return SearchMode.Kanji;
} else if (containsAscii) {
return SearchMode.English;
} else if (word.contains(hiraganaRegex) || word.contains(katakanaRegex)) {
return SearchMode.Kana;
} else {
return SearchMode.MixedKana;
}
}
Future<List<int>> _fetchEntryIds(DatabaseExecutor connection, String word,
SearchMode searchMode, int pageSize, int? offset) async {
assert(
searchMode != SearchMode.Auto,
'Search mode should not be auto when fetching entry IDs',
);
assert(
word.isNotEmpty,
'Word should not be empty when fetching entry IDs',
);
late final List<int> entryIds;
if (searchMode == SearchMode.Kanji) {
entryIds = (await connection.query(
'JMdict_EntryByKanji',
where: 'kanji LIKE ?',
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
} else if (searchMode == SearchMode.Kana) {
entryIds = (await connection.query(
'JMdict_EntryByKana',
where: 'kana LIKE ?',
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
} else {
entryIds = (await connection.query(
'JMdict_EntryByEnglish',
where: 'english LIKE ?',
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
}
return entryIds;
}
Future<List<WordSearchResult>?> searchWordWithDbConnection(
DatabaseExecutor connection,
String word, {
SearchMode searchMode = SearchMode.Auto,
int page = 0,
int pageSize = 10,
}) async {
if (word.isEmpty) {
return null;
}
if (searchMode == SearchMode.Auto) {
searchMode = _determineSearchMode(word);
}
final offset = page * pageSize;
final List<int> entryIds = await _fetchEntryIds(
connection,
word,
searchMode,
pageSize,
offset,
);
if (entryIds.isEmpty) {
return [];
}
late final List<Map<String, Object?>> senses;
final Future<List<Map<String, Object?>>> senses_query = connection.query(
'JMdict_Sense',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> readingElements;
final Future<List<Map<String, Object?>>> readingElements_query =
connection.query(
'JMdict_ReadingElement',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> kanjiElements;
final Future<List<Map<String, Object?>>> kanjiElements_query =
connection.query(
'JMdict_KanjiElement',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> jlptTags;
final Future<List<Map<String, Object?>>> jlptTags_query = connection.query(
'JMdict_JLPTTag',
where: 'entryId IN (${entryIds.join(',')})',
);
late final List<Map<String, Object?>> commonEntries;
final Future<List<Map<String, Object?>>> commonEntries_query =
connection.query(
'JMdict_EntryCommon',
where: 'entryId IN (${entryIds.join(',')})',
);
await Future.wait([
senses_query.then((value) => senses = value),
readingElements_query.then((value) => readingElements = value),
kanjiElements_query.then((value) => kanjiElements = value),
jlptTags_query.then((value) => jlptTags = value),
commonEntries_query.then((value) => commonEntries = value),
]);
// Sense queries
final senseIds = senses.map((sense) => sense['senseId'] as int).toList();
late final List<Map<String, Object?>> senseAntonyms;
final Future<List<Map<String, Object?>>> senseAntonyms_query =
connection.rawQuery("""
SELECT
JMdict_SenseAntonym.senseId,
JMdict_SenseAntonym.ambiguous,
JMdict_SenseAntonym.xrefEntryId,
JMdict_BaseAndFurigana.base,
JMdict_BaseAndFurigana.furigana
FROM JMdict_SenseAntonym
JOIN "JMdict_BaseAndFurigana"
ON JMdict_SenseAntonym.xrefEntryId = JMdict_BaseAndFurigana.entryId
WHERE
senseId IN (${senseIds.join(',')})
AND COALESCE("JMdict_BaseAndFurigana"."kanjiOrderNum", 1)
+ "JMdict_BaseAndFurigana"."readingOrderNum"
= 2
ORDER BY
JMdict_SenseAntonym.senseId,
JMdict_SenseAntonym.xrefEntryId
""");
late final List<Map<String, Object?>> senseDialects;
final Future<List<Map<String, Object?>>> senseDialects_query =
connection.query(
'JMdict_SenseDialect',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseFields;
final Future<List<Map<String, Object?>>> senseFields_query = connection.query(
'JMdict_SenseField',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseGlossaries;
final Future<List<Map<String, Object?>>> senseGlossaries_query =
connection.query(
'JMdict_SenseGlossary',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseInfos;
final Future<List<Map<String, Object?>>> senseInfos_query = connection.query(
'JMdict_SenseInfo',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseLanguageSources;
final Future<List<Map<String, Object?>>> senseLanguageSources_query =
connection.query(
'JMdict_SenseLanguageSource',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseMiscs;
final Future<List<Map<String, Object?>>> senseMiscs_query = connection.query(
'JMdict_SenseMisc',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> sensePOSs;
final Future<List<Map<String, Object?>>> sensePOSs_query = connection.query(
'JMdict_SensePOS',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseRestrictedToKanjis;
final Future<List<Map<String, Object?>>> senseRestrictedToKanjis_query =
connection.query(
'JMdict_SenseRestrictedToKanji',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseRestrictedToReadings;
final Future<List<Map<String, Object?>>> senseRestrictedToReadings_query =
connection.query(
'JMdict_SenseRestrictedToReading',
where: 'senseId IN (${senseIds.join(',')})',
);
late final List<Map<String, Object?>> senseSeeAlsos;
final Future<List<Map<String, Object?>>> senseSeeAlsos_query =
connection.rawQuery("""
SELECT
JMdict_SenseSeeAlso.senseId,
JMdict_SenseSeeAlso.ambiguous,
JMdict_SenseSeeAlso.xrefEntryId,
JMdict_BaseAndFurigana.base,
JMdict_BaseAndFurigana.furigana
FROM JMdict_SenseSeeAlso
JOIN "JMdict_BaseAndFurigana"
ON JMdict_SenseSeeAlso.xrefEntryId = JMdict_BaseAndFurigana.entryId
WHERE
senseId IN (${senseIds.join(',')})
AND COALESCE("JMdict_BaseAndFurigana"."kanjiOrderNum", 1)
+ "JMdict_BaseAndFurigana"."readingOrderNum"
= 2
ORDER BY
JMdict_SenseSeeAlso.senseId,
JMdict_SenseSeeAlso.xrefEntryId
""");
late final List<Map<String, Object?>> exampleSentences;
final Future<List<Map<String, Object?>>> exampleSentences_query =
connection.query(
'JMdict_ExampleSentence',
where: 'senseId IN (${senseIds.join(',')})',
);
// Reading queries
final readingIds = readingElements
.map((element) => (
element['entryId'] as int,
escapeStringValue(element['reading'] as String)
))
.toList();
late final List<Map<String, Object?>> readingElementInfos;
final Future<List<Map<String, Object?>>> readingElementInfos_query =
connection.query(
'JMdict_ReadingElementInfo',
where: '(entryId, reading) IN (${readingIds.join(',')})',
);
late final List<Map<String, Object?>> readingElementRestrictions;
final Future<List<Map<String, Object?>>> readingElementRestrictions_query =
connection.query(
'JMdict_ReadingElementRestriction',
where: '(entryId, reading) IN (${readingIds.join(',')})',
);
// Kanji queries
final kanjiIds = kanjiElements
.map((element) => (
element['entryId'] as int,
escapeStringValue(element['reading'] as String)
))
.toList();
late final List<Map<String, Object?>> kanjiElementInfos;
final Future<List<Map<String, Object?>>> kanjiElementInfos_query =
connection.query(
'JMdict_KanjiElementInfo',
where: '(entryId, reading) IN (${kanjiIds.join(',')})',
);
await Future.wait([
senseAntonyms_query.then((value) => senseAntonyms = value),
senseDialects_query.then((value) => senseDialects = value),
senseFields_query.then((value) => senseFields = value),
senseGlossaries_query.then((value) => senseGlossaries = value),
senseInfos_query.then((value) => senseInfos = value),
senseLanguageSources_query.then((value) => senseLanguageSources = value),
senseMiscs_query.then((value) => senseMiscs = value),
sensePOSs_query.then((value) => sensePOSs = value),
senseRestrictedToKanjis_query
.then((value) => senseRestrictedToKanjis = value),
senseRestrictedToReadings_query
.then((value) => senseRestrictedToReadings = value),
senseSeeAlsos_query.then((value) => senseSeeAlsos = value),
exampleSentences_query.then((value) => exampleSentences = value),
readingElementInfos_query.then((value) => readingElementInfos = value),
readingElementRestrictions_query
.then((value) => readingElementRestrictions = value),
kanjiElementInfos_query.then((value) => kanjiElementInfos = value),
]);
final result = _regroupWordSearchResults(
entryIds: entryIds,
readingElements: readingElements,
kanjiElements: kanjiElements,
jlptTags: jlptTags,
commonEntries: commonEntries,
senses: senses,
senseAntonyms: senseAntonyms,
senseDialects: senseDialects,
senseFields: senseFields,
senseGlossaries: senseGlossaries,
senseInfos: senseInfos,
senseLanguageSources: senseLanguageSources,
senseMiscs: senseMiscs,
sensePOSs: sensePOSs,
senseRestrictedToKanjis: senseRestrictedToKanjis,
senseRestrictedToReadings: senseRestrictedToReadings,
senseSeeAlsos: senseSeeAlsos,
exampleSentences: exampleSentences,
readingElementInfos: readingElementInfos,
readingElementRestrictions: readingElementRestrictions,
kanjiElementInfos: kanjiElementInfos,
);
return result;
}
List<WordSearchResult> _regroupWordSearchResults({
List<WordSearchResult> regroupWordSearchResults({
required List<int> entryIds,
required List<Map<String, Object?>> readingElements,
required List<Map<String, Object?>> kanjiElements,

View File

@@ -0,0 +1,78 @@
// TODO: Support globs
// TODO: Support tags
// TODO: Prefer original kana type when sorting results
// TODO: Support mixing kana and romaji
//
import 'package:jadb/models/word_search/word_search_result.dart';
import 'package:jadb/search/word_search/data_query.dart';
import 'package:jadb/search/word_search/entry_id_query.dart';
import 'package:jadb/search/word_search/regrouping.dart';
import 'package:sqflite_common/sqlite_api.dart';
enum SearchMode {
Auto,
English,
Kanji,
MixedKanji,
Kana,
MixedKana,
}
Future<List<WordSearchResult>?> searchWordWithDbConnection(
DatabaseExecutor connection,
String word, {
SearchMode searchMode = SearchMode.Auto,
int page = 0,
int pageSize = 10,
}) async {
if (word.isEmpty) {
return null;
}
final offset = page * pageSize;
final List<int> entryIds = await fetchEntryIds(
connection,
word,
searchMode,
pageSize,
offset,
);
if (entryIds.isEmpty) {
return [];
}
final LinearWordQueryData linearWordQueryData = await fetchLinearWordQueryData(
connection,
entryIds,
);
final result = regroupWordSearchResults(
entryIds: entryIds,
readingElements: linearWordQueryData.readingElements,
kanjiElements: linearWordQueryData.kanjiElements,
jlptTags: linearWordQueryData.jlptTags,
commonEntries: linearWordQueryData.commonEntries,
senses: linearWordQueryData.senses,
senseAntonyms: linearWordQueryData.senseAntonyms,
senseDialects: linearWordQueryData.senseDialects,
senseFields: linearWordQueryData.senseFields,
senseGlossaries: linearWordQueryData.senseGlossaries,
senseInfos: linearWordQueryData.senseInfos,
senseLanguageSources: linearWordQueryData.senseLanguageSources,
senseMiscs: linearWordQueryData.senseMiscs,
sensePOSs: linearWordQueryData.sensePOSs,
senseRestrictedToKanjis: linearWordQueryData.senseRestrictedToKanjis,
senseRestrictedToReadings: linearWordQueryData.senseRestrictedToReadings,
senseSeeAlsos: linearWordQueryData.senseSeeAlsos,
exampleSentences: linearWordQueryData.exampleSentences,
readingElementInfos: linearWordQueryData.readingElementInfos,
readingElementRestrictions: linearWordQueryData.readingElementRestrictions,
kanjiElementInfos: linearWordQueryData.kanjiElementInfos,
);
return result;
}