Flutter搜索功能插件searchbase的使用
Flutter搜索功能插件searchbase的使用
searchbase
是一个轻量级且与平台无关的库,提供了创建由Elasticsearch驱动的搜索体验所需的框架。本文将介绍如何在Flutter中使用 searchbase
插件来实现搜索功能,并提供完整的示例代码。
简单示例
以下示例创建了一个简单的搜索小部件,根据输入值渲染结果。
Dart代码
import 'dart:html';
import 'package:searchbase/searchbase.dart';
void main() {
final index = 'gitxplore-app';
final url = 'https://@appbase-demo-ansible-abxiydt-arc.searchbase.io';
final credentials = 'a03a1cb71321:75b6603d-9456-4a5a-af6b-a487b309eb61';
// 实例化 SearchController
final searchController = SearchController(
index, // Elasticsearch索引名称
url, // Appbase URL
credentials, // Appbase凭据
'search-widget', // 搜索小部件唯一标识符
dataField: ['name', 'description', 'name.search', 'fullname', 'owner', 'topics'],
value: ''
);
// 获取输入元素
final searchElement = querySelector('#search');
// 绑定 searchController 值到输入值
searchElement.value = searchController.value;
// 更新搜索输入值以触发查询
searchElement.addEventListener('input', (e) {
searchController.setValue(e.target.value,
options: Options(triggerDefaultQuery: true));
});
// 当搜索结果更新时构建DOM
searchController.subscribeToStateChanges((change) {
final results = change.Results!.next;
final resultsElement = querySelector('#results');
resultsElement.innerHTML = '';
results.data.forEach((element) {
var node = document.createElement('li'); // 创建 <li> 节点
var resultNode = document.createTextNode(element.name); // 创建文本节点
node.append(resultNode); // 将文本附加到 <li>
resultsElement.append(node);
});
}, [KeysToSubscribe.Results]);
// 在初始加载时获取默认结果
searchController.triggerDefaultQuery();
}
HTML代码
<input placeholder="type to search" id="search" />
<div id="results"></div>
使用Facet的示例
以下示例创建了三个小部件:一个用于执行搜索的小部件、一个用于过滤GitHub仓库的语言过滤器小部件和一个用于渲染结果的小部件。
Dart代码
import 'dart:html';
import 'package:searchbase/searchbase.dart';
void main() {
final index = 'gitxplore-app';
final url = 'https://@appbase-demo-ansible-abxiydt-arc.searchbase.io';
final credentials = 'a03a1cb71321:75b6603d-9456-4a5a-af6b-a487b309eb61';
final searchbase = SearchBase(index, url, credentials,
appbaseConfig: AppbaseSettings(recordAnalytics: true));
// 注册搜索小部件
final searchController = searchbase.register('search-widget', {
'enablePopularSuggestions': true,
'dataField': [
'name',
'description',
'name.raw',
'fullname',
'owner',
'topics'
]
});
// 注册语言过滤器小部件
final filterWidget = searchbase.register('language-filter', {
'type': QueryType.term,
'dataField': 'language.keyword',
'react': {'and': 'search-widget'},
'value': List<String>()
});
// 注册结果小部件
final resultWidget = searchbase.register('result-widget', {
'dataField': 'name',
'react': {
'and': ['search-widget', 'language-filter']
},
});
// 渲染结果
querySelector('#output').innerHtml = """
<div id="root">
<h2 class="text-center">Searchbase Demo with Facet</h2>
<div id="autocomplete" class="autocomplete">
<input class="autocomplete-input" id="input" />
<ul class="autocomplete-result-list"></ul>
</div>
<div class="row">
<div class="col">
<div class="filter" id="language-filter"></div>
</div>
<div class="col">
<div id="results">
<div class="loading">Loading results... </div>
</div>
</div>
</div>
</div>
""";
final input = querySelector('#input');
void handleInput(e) {
searchController.setValue(e.target.value,
options: Options(triggerDefaultQuery: true));
}
input.addEventListener('input', handleInput);
void handleKeyPress(e) {
if (e.key == 'Enter') {
e.preventDefault();
searchController.triggerCustomQuery();
}
}
input.addEventListener('keydown', handleKeyPress);
final resultElement = querySelector('#results');
// 获取初始结果
resultWidget.triggerDefaultQuery();
// 订阅结果变化并更新结果列表
resultWidget.subscribeToStateChanges((change) {
final results = change.Results!.next;
final items = results.data?.map((i) {
return """
<div id=${i['_id']} class="result-set">
<div class="image">
<img src=${i['avatar']} alt=${i['name']} />
</div>
<div class="details">
<h4>${i['name']}</h4>
<p>${i['description']}</p>
</div>
</div>""";
});
final resultStats = """<p class="results-stats">
Showing ${results.numberOfResults} in ${results.time}ms
<p>""";
resultElement.setInnerHtml("${resultStats}${items.join('')}",
validator: new NodeValidatorBuilder.common()
..allowHtml5()
..allowElement('img',
attributes: ['src'], uriPolicy: new DefaultUriPolicy()));
}, [KeysToSubscribe.Results]);
// 获取初始过滤选项
filterWidget.triggerDefaultQuery();
// 订阅过滤选项的变化
filterWidget.subscribeToStateChanges((change) {
final aggregations = change.AggregationData!.next;
final container = document.getElementById('language-filter');
container.setInnerHtml('');
aggregations.data.forEach((i) {
if (i['_key'] != null) {
final checkbox = document.createElement('input');
checkbox.setAttribute('type', 'checkbox');
checkbox.setAttribute('name', i['_key']);
checkbox.setAttribute('value', i['_key']);
checkbox.id = i['_key'];
checkbox.addEventListener('click', (event) {
final List<String> values =
filterWidget.value != null ? filterWidget.value : [];
if (values.contains(i['_key'])) {
values.remove(i['_key']);
} else {
values.add(i['_key']);
}
filterWidget.setValue(values,
options: Options(stateChanges: true, triggerCustomQuery: true));
});
final label = document.createElement('label');
label.setAttribute('htmlFor', 'i._key');
label.setInnerHtml("${i['_key']}(${i['_doc_count']})");
final div = document.createElement('div');
div.append(checkbox);
div.append(label);
container.append(div);
}
});
}, [KeysToSubscribe.AggregationData]);
searchController.subscribeToStateChanges((change) {
print('Track State Updates');
print(change);
}, [KeysToSubscribe.Results]);
}
class DefaultUriPolicy implements UriPolicy {
DefaultUriPolicy();
bool allowsUri(String uri) {
return true;
}
}
通过以上示例,您可以轻松地在Flutter应用中集成 searchbase
插件来实现强大的搜索功能。
更多关于Flutter搜索功能插件searchbase的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter搜索功能插件searchbase的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用SearchBase插件来实现搜索功能的代码示例。SearchBase是一个专为Flutter设计的强大搜索解决方案,它能够与Firebase Firestore、Elasticsearch和Algolia等后端服务集成。
在这个示例中,我将展示如何配置SearchBase并使用它与Firebase Firestore进行基本的搜索操作。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加SearchBase的依赖:
dependencies:
flutter:
sdk: flutter
searchbase: ^latest_version # 请替换为实际的最新版本号
firebase_firestore: ^latest_version # 请替换为实际的最新版本号
2. 配置Firebase Firestore
确保你已经在Firebase项目中启用了Firestore数据库,并获取了配置信息。然后在你的Flutter项目中配置Firebase:
// 在你的main.dart或合适的位置
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_firestore/firebase_firestore.dart';
import 'package:flutter/material.dart';
import 'package:searchbase/searchbase.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
3. 使用SearchBase进行搜索
下面是一个完整的示例,展示了如何使用SearchBase与Firebase Firestore进行搜索:
import 'package:flutter/material.dart';
import 'package:firebase_firestore/firebase_firestore.dart';
import 'package:searchbase/searchbase.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SearchScreen(),
);
}
}
class SearchScreen extends StatefulWidget {
@override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
final SearchBaseController searchBaseController = SearchBaseController();
late CollectionReference<Map<String, dynamic>> firestoreCollection;
@override
void initState() {
super.initState();
// 初始化Firestore集合
firestoreCollection = FirebaseFirestore.instance.collection('your_collection_name');
// 配置SearchBase
searchBaseController.setDataSource({
'firestore': {
'collectionPath': 'your_collection_name',
'firestore': FirebaseFirestore.instance,
},
});
// 监听搜索变化
searchBaseController.addSnapshotListener((snapshot) {
// 处理搜索结果
print(snapshot.docs);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SearchBase Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
decoration: InputDecoration(
labelText: 'Search...',
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: () {
// 触发搜索
searchBaseController.query(
search: TextField.focusedTextContext(context),
);
},
),
),
onChanged: (value) {
// 实时搜索
searchBaseController.query(search: value);
},
),
SizedBox(height: 16),
Expanded(
child: searchBaseController.hasResults
? ListView.builder(
itemCount: searchBaseController.snapshot?.docs?.length ?? 0,
itemBuilder: (context, index) {
Map<String, dynamic> doc =
searchBaseController.snapshot?.docs?[index].data() as Map<String, dynamic>;
return ListTile(
title: Text(doc['name'] ?? ''), // 假设你的文档有一个'name'字段
);
})
: Center(child: Text('No Results')),
),
],
),
),
);
}
}
注意事项
- 配置Firestore规则:确保你的Firestore安全规则允许你进行搜索操作。
- 字段映射:根据你的数据模型调整字段映射。
- 错误处理:添加适当的错误处理逻辑,以处理网络问题或数据解析错误。
这个示例展示了如何使用SearchBase与Firebase Firestore进行基本的搜索操作。根据你的需求,你可以进一步自定义和扩展这个示例。