Flutter搜索索引插件lunr的使用
Flutter搜索索引插件lunr的使用
lunr
Lunr有点像Solr,但更小且不那么亮(基于olivernn/lunr.js。
示例
创建一个非常简单的的搜索索引可以使用以下代码:
var idx = lunr((builder) {
builder.field('title');
builder.field('body');
builder.add({
"title": "Twelfth-Night",
"body": "If music be the food of love, play on: Give me excess of it…",
"author": "William Shakespeare",
"id": "1"
});
});
然后进行搜索就像这样:
idx.search("love");
这会返回一个包含与搜索查询匹配程度以及相关元数据的文档列表:
[
{
"ref": "1",
"score": 0.3535533905932737,
"matchData": {
"metadata": {
"love": {
"body": {}
}
}
}
}
]
描述
Lunr是一个用于浏览器的小型全文搜索库。它对JSON文档进行索引,并提供一个简单的的搜索接口来检索最匹配文本查询的文档。
为什么使用
对于所有数据都存储在客户端的应用程序来说,在客户端进行搜索是有意义的。这样可以在服务器上减少额外的数据压缩服务。本地搜索索引更快,没有网络开销,并且即使在网络连接断开时仍然可用和可访问。
安装
只需将lunr包添加到您的代码中即可。
Dart:
dart pub add lunr
Flutter:
flutter pub add lunr
特性
- 支持全文字搜索(lunrjs即将支持14种语言)。
- 在查询时提升某些词或在整个文档上提升。
- 局部搜索特定字段。
- 模糊匹配带通配符或编辑距离的词。
贡献
以下是完整的示例代码:
import 'package:lunr/lunr.dart';
void main() async {
// 创建一个lunr实例
var idx = lunr((builder) {
// 添加字段
builder.field('title');
builder.field('body');
// 添加文档
builder.add({
"title": "Twelfth-Night",
"body": "If music be the food of love, play on: Give me excess of it…",
"author": "William Shakespeare",
"id": "1"
});
});
// 进行搜索
var results = idx.search("love");
// 打印搜索结果
for (var result in results) {
print(result);
}
}
更多关于Flutter搜索索引插件lunr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter搜索索引插件lunr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter应用中使用lunr搜索索引插件的示例代码。需要注意的是,lunr是一个JavaScript库,通常用于在客户端进行全文搜索。为了在Flutter中使用它,你可以通过WebView或者一些其他桥接技术来加载和运行lunr的JavaScript代码。这里,我将展示如何使用webview_flutter
插件来在Flutter中集成lunr。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加webview_flutter
插件的依赖:
dependencies:
flutter:
sdk: flutter
webview_flutter: ^2.0.10 # 请检查最新版本号
2. 创建lunr索引的HTML文件
在assets
文件夹中创建一个HTML文件(例如lunr_index.html
),这个文件将包含lunr库和初始化好的索引。
<!-- assets/lunr_index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lunr Search Index</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.8/lunr.min.js"></script>
<script>
// 示例数据
var docs = [
{"id": 1, "title": "First document", "body": "This is the first document we've added."},
{"id": 2, "title": "Second document", "body": "The second document is even more interesting!"},
{"id": 3, "title": "Third document", "body": "And this is the third one."},
{"id": 4, "title": "Fourth document", "body": "Is this the first document?"}
];
// 创建lunr索引
var idx = lunr(function () {
this.field('title', { boost: 10 });
this.field('body');
docs.forEach(function (doc) {
this.add(doc);
}, this);
});
// JavaScript接口函数,用于搜索
function search(query) {
var results = idx.search(query);
return results.map(function (result) {
return {
id: result.ref,
title: docs[result.ref - 1].title,
body: docs[result.ref - 1].body
};
});
}
</script>
</head>
<body>
</body>
</html>
3. 在Flutter中加载HTML文件并进行搜索
在你的Flutter代码中,使用WebView
加载这个HTML文件,并通过JavaScript接口进行搜索。
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Lunr Search Example'),
),
body: WebViewExample(),
),
);
}
}
class WebViewExample extends StatefulWidget {
@override
_WebViewExampleState createState() => _WebViewExampleState();
}
class _WebViewExampleState extends State<WebViewExample> {
late WebViewController _controller;
@override
Widget build(BuildContext context) {
return WebView(
initialUrl: Uri.dataFromString(
'''
<html>
<head>
<title>WebView Example</title>
</head>
<body>
<h1>Loading lunr_index.html...</h1>
<script>
window.onload = function() {
window.location.href = 'lunr_index.html';
}
</script>
</body>
</html>
''',
mimeType: 'text/html',
encoding: Encoding.getByName('utf-8')
).toString(),
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
);
}
Future<void> search(String query) async {
try {
// 调用JavaScript的search函数
var result = await _controller.evaluateJavascript('search("$query")');
// 解析结果(JSON字符串)
var searchResults = await jsonDecode(result);
// 显示结果(这里简单地打印到控制台)
print('Search Results: $searchResults');
// 你可以在这里更新UI来显示搜索结果
} catch (e) {
print('Failed to search: $e');
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: WebView(
initialUrl: Uri.dataFromString(
// 这里可以省略,因为我们在onWebViewCreated中重定向了
'',
mimeType: 'text/html',
encoding: Encoding.getByName('utf-8')
).toString(),
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
// 可以在这里加载资源文件,比如CSS、JS等(如果需要)
},
),
),
Padding(
padding: EdgeInsets.all(16.0),
child: TextField(
decoration: InputDecoration(labelText: 'Search'),
onEditingComplete: () {
_controller.evaluateJavascript('document.readyState').then((readyState) {
if (readyState == 'complete') {
search(textFieldController.text);
}
});
},
onSubmitted: (value) {
search(value);
},
controller: textFieldController,
),
),
],
);
}
}
// 注意:上面的代码缺少TextField的控制器定义,需要添加如下代码
final TextFieldController textFieldController = TextFieldController();
// 由于TextFieldController不能在类作用域直接初始化,你需要在某个Widget的build方法中
// 或者在initState中将其初始化为State的一部分。
注意:
- 上述代码是一个简化的示例,它展示了如何在Flutter中使用WebView加载HTML文件,并通过JavaScript接口进行搜索。
- 实际的Flutter应用中,你可能需要处理更多的边界情况,比如加载错误、资源文件的打包和访问等。
TextFieldController
的初始化需要放在State
类中,这里为了简洁,没有在代码中展示完整的初始化过程。- 在生产环境中,避免使用外部CDN加载lunr.js,最好是将lunr.js文件打包到应用中。
希望这个示例能帮助你在Flutter应用中集成lunr搜索索引!