全文搜索模块 - Cordova与OpenHarmony混合开发实战
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

📌 概述
全文搜索模块提供了快速搜索日记内容的功能。这个模块支持按关键词搜索日记的标题和内容,并提供了搜索结果的高亮显示和排序功能。通过Cordova框架,我们能够在Web层实现高效的搜索界面,同时利用OpenHarmony的全文索引能力加速搜索。
全文搜索模块采用了实时搜索设计,用户输入关键词时,应用会实时显示搜索结果。同时提供了搜索历史功能,用户可以快速重复之前的搜索。
🔗 完整流程
搜索执行流程:用户在搜索框中输入关键词,应用会实时执行搜索。搜索使用数据库的全文索引,快速返回匹配的日记。搜索结果按相关性排序,最相关的结果显示在最前面。
搜索结果展示流程:搜索结果以列表形式展示,每个结果项包含日记标题、摘要和匹配的关键词高亮。用户可以点击结果项打开完整的日记。
搜索历史管理流程:应用自动记录用户的搜索历史。用户可以在搜索框下方看到最近的搜索记录,点击可以快速重复搜索。用户也可以清除搜索历史。
🔧 Web代码实现
// 执行全文搜索
async function performSearch(keyword) {
if (!keyword || keyword.trim().length === 0) {
return [];
}
try {
const results = await db.searchDiaries(keyword);
// 记录搜索历史
await recordSearchHistory(keyword);
// 按相关性排序
return results.sort((a, b) => {
const aScore = calculateRelevance(a, keyword);
const bScore = calculateRelevance(b, keyword);
return bScore - aScore;
});
} catch (error) {
console.error('搜索失败:', error);
return [];
}
}
// 计算相关性分数
function calculateRelevance(diary, keyword) {
let score = 0;
const lowerKeyword = keyword.toLowerCase();
const lowerTitle = diary.title.toLowerCase();
const lowerContent = diary.content.toLowerCase();
// 标题中的匹配权重更高
if (lowerTitle.includes(lowerKeyword)) {
score += 10;
}
// 内容中的匹配
const contentMatches = (lowerContent.match(new RegExp(lowerKeyword, 'g')) || []).length;
score += contentMatches;
return score;
}
// 记录搜索历史
async function recordSearchHistory(keyword) {
try {
const history = await db.getSearchHistory();
const existingIndex = history.findIndex(h => h.keyword === keyword);
if (existingIndex >= 0) {
// 更新搜索时间
history[existingIndex].lastSearched = new Date();
} else {
// 添加新的搜索记录
history.unshift({
keyword: keyword,
lastSearched: new Date()
});
// 只保留最近50条
if (history.length > 50) {
history.pop();
}
}
await db.saveSearchHistory(history);
} catch (error) {
console.error('记录搜索历史失败:', error);
}
}
这些函数处理搜索执行、相关性计算和搜索历史记录。calculateRelevance函数根据关键词在标题和内容中的位置和频率计算相关性分数。
// 渲染搜索页面
async function renderSearch() {
const searchHistory = await db.getSearchHistory();
const html = `
<div class="search-container">
<div class="search-header">
<h1>全文搜索</h1>
<div class="search-box-wrapper">
<input type="text" id="search-input" placeholder="输入关键词搜索..." class="search-input">
<button class="btn-primary" onclick="executeSearch()">搜索</button>
</div>
</div>
<div class="search-history">
<h3>最近搜索</h3>
<div class="history-items">
${searchHistory.slice(0, 10).map(item => `
<button class="history-item" onclick="quickSearch('${item.keyword}')">
${item.keyword}
</button>
`).join('')}
</div>
<button class="btn-small" onclick="clearSearchHistory()">清除历史</button>
</div>
<div id="search-results"></div>
</div>
`;
document.getElementById('page-container').innerHTML = html;
attachSearchListeners();
}
// 执行搜索并显示结果
async function executeSearch() {
const keyword = document.getElementById('search-input').value;
const results = await performSearch(keyword);
const resultsHtml = `
<div class="search-results">
<h2>搜索结果 (${results.length})</h2>
${results.length > 0 ? `
<div class="results-list">
${results.map(result => ` <div class="result-item" onclick="app.navigateTo('diary-edit', ${result.id})"> <h3>${highlightKeyword(result.title, keyword)}</h3> <p class="result-excerpt">${highlightKeyword(result.content.substring(0, 200), keyword)}...</p> <div class="result-meta"> <span class="pet-tag">${result.petName}</span> <span class="result-date">${formatDate(result.createdAt)}</span> </div> </div> `).join('')}
</div>
` : `<p class="empty-state">未找到匹配的日记</p>`}
</div>
`;
document.getElementById('search-results').innerHTML = resultsHtml;
}
// 高亮关键词
function highlightKeyword(text, keyword) {
const regex = new RegExp(`(${keyword})`, 'gi');
return text.replace(regex, '<mark>$1</mark>');
}
这个渲染函数生成了搜索界面,包括搜索框、搜索历史和搜索结果。highlightKeyword函数在搜索结果中高亮显示匹配的关键词。
🔌 原生代码实现
// SearchPlugin.ets - 搜索原生插件
import { fileIo } from '@kit.BasicServicesKit';
@Entry
@Component
struct SearchPlugin {
// 建立全文索引
buildFullTextIndex(diaries: string, callback: (success: boolean) => void): void {
try {
const data = JSON.parse(diaries);
// 建立全文索引逻辑
console.log('[SearchPlugin] 全文索引已建立');
callback(true);
} catch (error) {
console.error('[SearchPlugin] 建立索引失败:', error);
callback(false);
}
}
// 执行全文搜索
performFullTextSearch(keyword: string, callback: (results: string) => void): void {
try {
// 全文搜索逻辑
const results = [];
callback(JSON.stringify(results));
} catch (error) {
console.error('[SearchPlugin] 搜索失败:', error);
callback(JSON.stringify([]));
}
}
build() {
Column() {
Web({ src: 'resource://rawfile/www/index.html', controller: new WebviewController() })
}
}
}
这个原生插件提供了全文索引和搜索功能。通过建立全文索引,我们能够加速搜索速度。
Web-Native通信代码
// 执行原生全文搜索
function performNativeFullTextSearch(keyword) {
return new Promise((resolve, reject) => {
cordova.exec(
(result) => {
try {
const results = JSON.parse(result);
resolve(results);
} catch (error) {
reject(error);
}
},
(error) => {
console.error('搜索失败:', error);
reject(error);
},
'SearchPlugin',
'performFullTextSearch',
[keyword]
);
});
}
这段代码展示了如何通过Cordova调用原生的全文搜索功能。
📝 总结
全文搜索模块展示了Cordova与OpenHarmony在搜索功能方面的应用。在Web层,我们实现了灵活的搜索界面和结果展示。在原生层,我们提供了全文索引和搜索功能。
通过相关性排序,用户可以快速找到最相关的日记。通过搜索历史,用户可以快速重复之前的搜索。通过Web-Native通信,我们能够充分利用OpenHarmony的搜索能力,为用户提供快速高效的搜索体验。
在实际开发中,建议实现搜索建议功能,提供高级搜索选项,并支持搜索结果的导出。
更多推荐
所有评论(0)