分享程式代碼相關筆記
目前文章總數:157 篇
最後更新:2024年 12月 07日
Lunr.js 是一個在瀏覽器中使用的小型全文搜尋函式庫。 它索引 JSON 文件並提供一個簡單的搜尋介面,用於檢索與文字查詢最匹配的文件。
Github 上的原文:
Description
Lunr.js is a small, full-text search library for use in the browser.
It indexes JSON documents and provides a simple search interface for retrieving documents that best match text queries.
讓前端純靜態頁面也能高效率搜尋資料。
若有以下三種需求,可以考慮引入使用:
1. 靜態網站生成器 | : | Lunr.js 常被用於靜態網站生成器(如 Jekyll、Hugo)中,為生成的靜態網站添加搜索功能。 |
2. 單頁應用 | : | 在單頁應用中,Lunr.js 可以用來在不依賴伺服器的情況下實現快速搜索 |
3. 文檔網站 | : | 用於文檔網站的搜索功能,使用戶能夠快速找到所需的信息。 |
若有以下三種需求,可以考慮引入使用:
1. 輕量級 | : | Lunr.js 無需伺服器支援,所有操作都在客戶端完成,因此特別適合靜態網站和單頁應用(SPA)。 |
2. 簡單易用 | : | 使用 Lunr.js 不需要繁瑣的配置,可以快速上手。通過簡單的 API 可以建立索引和進行搜索。 |
3. 全文檢索 | : | 使用 BM25 演算法,支持全文檢索,能夠處理和搜索大量文本數據。 |
4. 支持多語言 | : | 支持共 14 國語言,包含中文、英文 |
5. 可擴充性 | : | 官方的 API 文件也提供擴充的搜尋方式。 |
官方Guide中有快速使用方式,可以直接參考
或者使用以下準備的 Demo 範例
下載 lunr.js的 Libary 檔案,約100 kb
在 Html 的 Head 中引入:
<script src="https://github.com/olivernn/lunr.js/blob/master/lunr.js"></script>
從 javascript 中,建立一個索引的資料集 documents 變數:
//建立網站資料,作為索引
var documents = [{
"name": "Lunr",
"text": "Like Solr, but much smaller, and not as bright."
}, {
"name": "React",
"text": "A JavaScript library for building user interfaces."
}, {
"name": "Lodash",
"text": "A modern JavaScript utility library delivering modularity, performance & extras."
}, {
"name": "HTML",
"text": "JavaScript 是一個成熟的動態程式語言,應用於HTML 文件(document)"
}, {
"name": "Javascript",
"text": "JavaScript 是一個成熟的動態程式語言,應用於HTML 文件(document)"
}, {
"name": "Test",
"text": "JavaScript JavaProgram 123f53. ehubz,ewui"
}]
然後建立以下基本搜索代碼
// 1-1. lunr 基本搜索
var idx = lunr(function () {
this.ref('name')
this.field('text')
documents.forEach(function (doc) {
this.add(doc)
}, this)
})
以下是 6 種 Lunr.js 支持的搜尋方式
// 1-2. 轉換對應查詢方法
function MatchSearch(term, searchName) {
switch(searchName) {
case 'base':
return term;
case 'wildcards':
return '*' + term + '*';//包含
case 'fields':
return 'text:' + term;//只查指定 fields
case 'boots':
return term + '^10';//增加10倍權重
case 'fuzzy':
return term + '~1'; //1個char的模糊
case 'presence':
return '+' + term + ' +JavaProgram';// 包含查詢的內容 && 包含有 JavaProgram 資料
}
return term;
}
將 documents 索引資料轉成 Table Dom 元件顯示,便於觀察
// 2. 轉成畫面上的 Table 顯示
function createTable() {
var table = document.createElement("table");
var headerRow = document.createElement("tr");
table.style.borderCollapse = "collapse";
// Create header cells
for (var key in documents[0]) {
var headerCell = document.createElement("th");
headerCell.textContent = key;
headerCell.style.border = "1px solid #dddddd";
headerRow.appendChild(headerCell);
}
table.appendChild(headerRow);
// Create data rows
documents.forEach(function(documentItems) {
var row = document.createElement("tr");
for (var key in documentItems) {
var cell = document.createElement("td");
cell.textContent = documentItems[key];
cell.style.border = "1px solid #dddddd";
row.appendChild(cell);
}
table.appendChild(row);
});
return table;
}
執行查詢結果後顯示[筆數]、[條列]結果
// 3-1. lunr 的查詢結果顯示成條列
function lunr_search(term, searchName) {
document.getElementById('lunrsearchresults').innerHTML = '<ul></ul>';
if(term) {
// 3-2. 替換為搜尋方式的字詞
term = MatchSearch(term, searchName);
var results = idx.search(term);
document.getElementById('lunrsearchresults').innerHTML = "<p>共" + results.length + "筆,如下:</p>" + document.getElementById('lunrsearchresults').innerHTML;
//put results on the screen.
if (results.length > 0) {
for (var i = 0; i < results.length; i++) {
var ref = results[i]['ref'];
var name = documents.find(doc => doc.name === ref).name;
var text = documents.find(doc => doc.name === ref).text;
document.querySelectorAll('#lunrsearchresults ul')[0].innerHTML = document.querySelectorAll('#lunrsearchresults ul')[0].innerHTML + "<li class='lunrsearchresult'><a href=''><span class='title'>" + (i + 1) + ". " + name + "</span><br /><span class='body'>" + text + "</span><br /><span class='url'></span></a></li>";
}
} else {
document.querySelectorAll('#lunrsearchresults ul')[0].innerHTML = "<li class='lunrsearchresult'>查無結果</li>";
}
}
return false;
}
Html 上的所有元件建立如下:
<style>
#lunrsearchresults {padding-top: 0.2rem;}
.lunrsearchresult {padding-bottom: 1rem;}
.lunrsearchresult .title {color: #d9230f;}
.lunrsearchresult .url {color: silver;}
.lunrsearchresult a {display: block; color: #777;}
.lunrsearchresult a:hover, .lunrsearchresult a:focus {text-decoration: none;}
.lunrsearchresult a:hover .title {text-decoration: underline;}
</style>
<form>
<div id="buttonWrapper" style="display: flex;">
<p><button type="button" onclick="lunr_search(document.getElementById('lunrsearch').value , 'base');">Lunr 基本搜索</button></p>
<p><button type="button" onclick="lunr_search(document.getElementById('lunrsearch').value , 'wildcards');">通配符(wildcards) 搜索</button></p>
<p><button type="button" onclick="lunr_search(document.getElementById('lunrsearch').value , 'fields');">字段(fields) 搜索</button></p>
<p><button type="button" onclick="lunr_search(document.getElementById('lunrsearch').value , 'boots');">權重提升(boosts) 搜索</button></p>
<p><button type="button" onclick="lunr_search(document.getElementById('lunrsearch').value , 'fuzzy');">模糊匹配(fuzzy matches) 搜索</button></p>
<p><button type="button" onclick="lunr_search(document.getElementById('lunrsearch').value , 'presence');">指定關鍵詞(term presence) 搜索</button></p>
</div>
<p><input type="text" class="form-control" id="lunrsearch" name="q" maxlength="255" value="" placeholder="查詢關鍵字" /></p>
</form>
<div id="lunrsearchresults">
<ul></ul>
</div>
<br/><br/><hr><br/><br/>
<div id="contentboard">
Demo連結上方有 6 個搜尋方法
中間是輸入查詢資料
最下方是當前的所有已建立的索引資料
輸入 Javascript 後,可以找到 5 筆完全匹配此文字的資料
輸入 small 後,因為匹配了 * 所以會變成 small* 查詢,因此可以找到 1 筆 Text內含有的資料
case 'wildcards':
return '*' + term + '*';//包含
針對 text: 查詢,如果有出現在 text 中才會查詢到資料
case 'fields':
return 'text:' + term;//只查指定 fields
boosts說明 提高某個搜尋的字詞比其他字詞更高的價值,使期在特定條件下容易搜尋到
以此例來說,輸入的字詞增加 10 倍權重,但需對後面資料賦予單詞。
case 'boots':
return term + '^10';//增加10倍權重
針對 1 個字元的模糊搜尋,以 uch 舉例,省略了 m 字元,使其可以找到含有 much 的資料
case 'fuzzy':
return term + '~1'; //1個char的模糊
用 + 代表必須包含,用 - 代表不包含,以此例就是查詢 Test 並且包含有 JavaProgram 的資料
case 'presence':
return '+' + term + ' +JavaProgram';// 包含查詢的內容 && 包含有 JavaProgram 資料
輸入 ‘文件’ 理論上應該要可以搜尋到 2 筆資料,但預設的 Lunr.js 是不支援中文
Lunr-Chinese 的 GitHub有分享使用中文分隔字詞的搜尋
替換原本引用的 lunr.js 為以下
<script src="https://raw.githubusercontent.com/Wiredcraft/lunr-chinese/master/lunr-chinese.js"></script>
可以發現中文字詞能正確查找了