全文搜索 - Cordova 与 OpenHarmony 混合开发实战
本文介绍了MovieTracker应用的全文搜索模块,该模块支持影片标题、导演、演员等多字段搜索。主要功能包括实时搜索(采用防抖技术优化)、搜索历史记录、结果高亮显示和搜索统计。文章详细说明了搜索流程:输入处理→搜索执行→结果优化,并提供了Web端的HTML结构和JavaScript实现代码,包含搜索缓存、结果排序和高亮等核心功能。该模块通过Cordova框架与OpenHarmony原生能力结合,
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

📌 模块概述
全文搜索模块是MovieTracker应用中用于快速查找影片的功能。用户可以输入影片标题、导演、演员等关键词,系统会实时搜索并显示匹配的影片。全文搜索提供了最快速的影片查找方式,支持模糊匹配和多字段搜索。
该模块的主要功能包括:实时搜索、搜索历史、热门搜索词、搜索结果高亮、搜索统计等。通过Cordova框架与OpenHarmony原生能力的结合,实现了高效的全文搜索和搜索优化。
全文搜索需要处理大量的搜索请求,因此需要优化搜索性能。可以使用防抖技术延迟搜索请求,同时在数据库中建立索引以加快查询速度。
🔗 完整流程
第一步:搜索输入与防抖处理
当用户在搜索框中输入内容时,系统需要实时搜索。为了避免频繁的数据库查询,需要使用防抖技术延迟搜索请求。当用户停止输入一段时间后,才执行搜索操作。
搜索输入需要处理特殊字符,防止SQL注入。同时需要记录搜索历史,方便用户快速访问之前的搜索。
第二步:搜索执行与结果处理
搜索执行时需要在多个字段中进行搜索,如影片标题、导演、演员、描述等。搜索结果需要按相关性排序,最相关的结果显示在前面。同时需要处理搜索结果为空的情况,提示用户没有找到匹配的影片。
搜索结果需要进行高亮显示,将匹配的关键词标记出来,帮助用户快速识别匹配内容。
第三步:搜索优化与统计
搜索模块需要记录搜索统计信息,如搜索词频率、搜索结果数量等。这些统计信息可以用于优化搜索算法和提供热门搜索词建议。
同时需要优化搜索性能,使用缓存机制存储热门搜索词的结果,避免重复搜索。
🔧 Web代码实现
全文搜索HTML结构
<div id="search-page" class="page">
<div class="search-container">
<input type="text" id="search-input" placeholder="搜索影片标题、导演、演员..."
class="search-box" onkeyup="handleSearchInput(event)">
<button class="btn btn-primary" onclick="clearSearch()">清空</button>
</div>
<div class="search-suggestions" id="suggestions-container" style="display: none;"></div>
<div class="search-results" id="search-results"></div>
<div class="search-history">
<h3>搜索历史</h3>
<div id="history-list" class="history-list"></div>
</div>
</div>
这个HTML结构定义了全文搜索页面的布局。搜索框用于输入搜索关键词。suggestions-container显示搜索建议。search-results显示搜索结果。history-list显示搜索历史。
搜索实现
let searchTimeout;
const searchCache = {};
function handleSearchInput(event) {
const keyword = event.target.value.trim();
clearTimeout(searchTimeout);
if (keyword.length === 0) {
document.getElementById('search-results').innerHTML = '';
document.getElementById('suggestions-container').style.display = 'none';
return;
}
// 防抖:延迟300ms执行搜索
searchTimeout = setTimeout(() => {
performSearch(keyword);
}, 300);
}
async function performSearch(keyword) {
try {
// 检查缓存
if (searchCache[keyword]) {
displaySearchResults(searchCache[keyword], keyword);
return;
}
const allMovies = await db.getAllMovies();
// 搜索匹配的影片
const results = allMovies.filter(movie => {
const searchText = `${movie.title} ${movie.director} ${movie.actors || ''} ${movie.description || ''}`.toLowerCase();
return searchText.includes(keyword.toLowerCase());
});
// 按相关性排序
results.sort((a, b) => {
const aTitle = a.title.toLowerCase().includes(keyword.toLowerCase()) ? 0 : 1;
const bTitle = b.title.toLowerCase().includes(keyword.toLowerCase()) ? 0 : 1;
return aTitle - bTitle;
});
// 缓存结果
searchCache[keyword] = results;
// 记录搜索历史
saveSearchHistory(keyword);
displaySearchResults(results, keyword);
} catch (error) {
console.error('搜索失败:', error);
showError('搜索失败');
}
}
function displaySearchResults(results, keyword) {
const container = document.getElementById('search-results');
container.innerHTML = '';
if (results.length === 0) {
container.innerHTML = `<p class="empty-message">未找到包含"${keyword}"的影片</p>`;
return;
}
const resultsList = document.createElement('div');
resultsList.className = 'results-list';
results.forEach(movie => {
const resultItem = document.createElement('div');
resultItem.className = 'result-item';
// 高亮关键词
const highlightedTitle = highlightKeyword(movie.title, keyword);
resultItem.innerHTML = `
<div class="result-title">${highlightedTitle}</div>
<div class="result-meta">
<span>${movie.year}</span>
<span>${movie.director}</span>
<span>⭐ ${movie.rating || '未评分'}</span>
</div>
<div class="result-actions">
<button onclick="app.navigateTo('movie-detail', ${movie.id})" class="btn btn-small">查看详情</button>
</div>
`;
resultsList.appendChild(resultItem);
});
container.appendChild(resultsList);
}
function highlightKeyword(text, keyword) {
const regex = new RegExp(`(${keyword})`, 'gi');
return text.replace(regex, '<mark>$1</mark>');
}
这个函数实现了全文搜索功能。handleSearchInput()处理搜索输入,使用防抖技术延迟搜索。performSearch()执行实际搜索,支持多字段搜索和缓存。displaySearchResults()显示搜索结果并高亮关键词。
搜索历史管理
async function saveSearchHistory(keyword) {
try {
const history = await db.getSearchHistory();
// 移除重复的搜索词
const filtered = history.filter(h => h.keyword !== keyword);
// 添加新的搜索词到开头
filtered.unshift({
keyword: keyword,
timestamp: Date.now()
});
// 只保留最近的20条搜索历史
const limited = filtered.slice(0, 20);
await db.saveSearchHistory(limited);
loadSearchHistory();
} catch (error) {
console.error('保存搜索历史失败:', error);
}
}
async function loadSearchHistory() {
try {
const history = await db.getSearchHistory();
const container = document.getElementById('history-list');
container.innerHTML = '';
if (history.length === 0) {
container.innerHTML = '<p class="empty-message">暂无搜索历史</p>';
return;
}
history.slice(0, 10).forEach(item => {
const historyItem = document.createElement('div');
historyItem.className = 'history-item';
historyItem.innerHTML = `
<span onclick="searchByHistory('${item.keyword}')" class="history-keyword">${item.keyword}</span>
<button onclick="deleteHistoryItem('${item.keyword}')" class="btn btn-small btn-danger">删除</button>
`;
container.appendChild(historyItem);
});
} catch (error) {
console.error('加载搜索历史失败:', error);
}
}
function searchByHistory(keyword) {
document.getElementById('search-input').value = keyword;
performSearch(keyword);
}
这个函数实现了搜索历史的管理。saveSearchHistory()保存搜索词到历史记录,loadSearchHistory()加载并显示搜索历史。
🔌 OpenHarmony原生代码
全文搜索插件
// SearchPlugin.ets
import { webview } from '@kit.ArkWeb';
import { common } from '@kit.AbilityKit';
export class SearchPlugin {
private context: common.UIAbilityContext;
constructor(context: common.UIAbilityContext) {
this.context = context;
}
public registerSearch(controller: webview.WebviewController): void {
controller.registerJavaScriptProxy({
object: new SearchBridge(),
name: 'searchNative',
methodList: ['getSearchSuggestions', 'getHotSearches']
});
}
}
这个OpenHarmony原生插件为全文搜索提供了搜索建议和热门搜索功能。
搜索建议实现
export class SearchBridge {
public getSearchSuggestions(keyword: string, historyJson: string): string {
try {
const history = JSON.parse(historyJson);
// 从历史记录中获取相关建议
const suggestions = history
.filter(h => h.keyword.includes(keyword))
.map(h => h.keyword)
.slice(0, 5);
return JSON.stringify({
suggestions: suggestions,
count: suggestions.length
});
} catch (error) {
return JSON.stringify({
error: error.message
});
}
}
public getHotSearches(historyJson: string): string {
try {
const history = JSON.parse(historyJson);
// 统计搜索频率
const frequency: any = {};
history.forEach((h: any) => {
frequency[h.keyword] = (frequency[h.keyword] || 0) + 1;
});
// 按频率排序
const hotSearches = Object.entries(frequency)
.sort((a: any, b: any) => b[1] - a[1])
.slice(0, 10)
.map(([keyword]) => keyword);
return JSON.stringify({
hotSearches: hotSearches,
count: hotSearches.length
});
} catch (error) {
return JSON.stringify({
error: error.message
});
}
}
}
这个类实现了搜索建议和热门搜索功能。getSearchSuggestions()基于搜索历史提供搜索建议,getHotSearches()返回最热门的搜索词。
Web-Native通信
调用原生搜索功能
async function getSearchSuggestions(keyword) {
try {
const history = await db.getSearchHistory();
if (window.searchNative) {
const suggestResult = window.searchNative.getSearchSuggestions(
keyword,
JSON.stringify(history)
);
const result = JSON.parse(suggestResult);
displaySuggestions(result.suggestions);
}
} catch (error) {
console.error('获取搜索建议失败:', error);
}
}
async function displayHotSearches() {
try {
const history = await db.getSearchHistory();
if (window.searchNative) {
const hotResult = window.searchNative.getHotSearches(JSON.stringify(history));
const result = JSON.parse(hotResult);
console.log('热门搜索:', result.hotSearches);
}
} catch (error) {
console.error('获取热门搜索失败:', error);
}
}
这个函数展示了如何调用OpenHarmony原生的搜索建议功能。在用户输入时获取搜索建议,帮助用户快速找到想要的影片。
📝 总结
全文搜索模块展示了Cordova与OpenHarmony混合开发中的高效搜索和智能建议功能。通过Web层提供用户友好的搜索界面,同时利用OpenHarmony原生能力进行搜索优化和热门搜索分析。
在实现这个模块时,需要注意搜索性能的优化、搜索结果的相关性排序、以及搜索建议的准确性。通过合理的架构设计和优化策略,可以构建出高效、易用的全文搜索功能。
更多推荐
所有评论(0)