使用 Javascript 在客户端机器上进行基于全文的搜索
Posted
技术标签:
【中文标题】使用 Javascript 在客户端机器上进行基于全文的搜索【英文标题】:Full text based Search on Client Machine using Java Script 【发布时间】:2013-03-27 08:04:11 【问题描述】:我正在尝试在客户端计算机上实现基于全文的搜索功能。
我发现Lunr.js 部分满足了我的要求,但它必须加载到像 Apache 这样的服务器上,然后才能完美运行。
就我而言,客户端机器不会安装任何服务器或数据库。一个目录中只有一堆静态 html 文件,一个索引文件接受来自搜索框的用户输入,该搜索框在这些静态 HTML 文件中搜索此字符串。
Google 搜索发现一些有趣的词(可能)在我的项目中需要:innerHtml
、DOM
、iframes
和 RegExp
。
请根据您的回答提出我的疑问。提前致谢
【问题讨论】:
您想在文件中搜索吗?很确定你不能在客户端。 在文件中搜索客户端将是矫枉过正。您将不得不使用 javascript 将所有文件传输到客户端,这完全是个坏主意。每个页面都提供有限的资源,以及一些使用低速连接的人。 仅当您有少量文本时才可用。 @Sanya_Zol 不传输文件。所有 HTML 文件都存在于客户的本地机器上。当用户搜索 Word 时,只需搜索所有这些 HTML 文件... @highlander141 你不能这样做(因为本地页面安全上下文只有一页),至少直接。但是您可以:使用XML index as Milind Anantwar suggested(但这需要将所有数据嵌入/转换到一个文件中)或使用搜索软件(可以是html application and done in JavaScript(注意hta 文件扩展名)以及software like google desktop @Sanya_Zol +1 用于提及 HTML 应用程序。这个搜索可以像文件中的字符串/短语一样吗?? 【参考方案1】:我可以想到一种方法 - 您可以使用 XMLHttpRequest 获取本地文件。默认情况下不允许这样做,但例如可以使用以下参数启动 chromium:
--allow-file-access-from-files
您必须浏览所有要查看的文件并通过stripping html tags 手动实现搜索并执行正则表达式,这应该不难。
我在 chromium 中测试了以下代码:
var xmlhttp = new XMLHttpRequest();
var url = "file:///your-file.html";
xmlhttp.open('GET', url, true);
xmlhttp.onerror = function(e) console.log('Problems' + e); ;
xmlhttp.onreadystatechange=function()
if (xmlhttp.readyState === 4 && xmlhttp.status === 0)
console.log("Fetched: ");
console.log(xmlhttp.responseText);
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
// ....
else if (xmlhttp.readyState==4 && xmlhttp.status != 200)
// ....
xmlhttp.send();
【讨论】:
【参考方案2】:虽然我没试过用这种方式,你可以看看jIO(Github)
jIO 可用于跨多个存储(浏览器 localstorage、webDav、xWiki、S3...)管理和同步 JSON 文档。存储可以被索引,jIO 带有自己的查询模块,称为 complexQueries,也可以独立使用。
如果您通过 Ajax 请求页面并提取页面的全文/HTML,只需将其作为文档转储到 jIO 中。
三种方法(所有示例均来自jIO documentation):
1) 使用普通的本地存储和复杂的查询 在 jIO 中为您想要搜索的每个文档创建一个文档。所以在设置你的 jIO 之后:
var mySearchFiles = JIO.newJio(
"type" : "local",
"username" : "whatever",
"application_name" : "fulltextsearch"
);
将完整的 HTML/提取文本(本地存储大小限制...)添加为文档,如下所示:
mySearchFiles.put(
"_id": "your_id",
"search_result_string": "page_title/page_filename",
"searchable_text": "your_text_to_be_searched_goes_here",
function (err, response)
// console.log(response) =
//
// "ok": true,
// "id": "your_id",
//
);
在搜索时使用 _id
或其他自定义键作为您希望从 jIO 返回的内容。
然后使用 allDocs 方法在您的 jIO 上运行复杂查询(here 是一个用于处理复杂查询的示例页面):
// here you construct your basic query
var query_object =
"query":
"filter":
// records from/to to be returned
"limit":[0,10],
// sort direction
"sort_on":[[search_result_string, "ascending"]],
// what fields to return
"select_list":[["search_result_string"]]
,
// wildchard
"wildcard_character":'%'
;
// build your query - if user entered the variable "search_term":
var search = "searchable_text: = %" + search_term + "%";
// add to query object
query_object.query.query = search;
// run the search
mySearchFiles.allDocs(
query_object,
function (err, response)
console.log(response);
);
这应该返回你想要的search_result_string
。我不知道在大文本上搜索的速度有多快,但如果需要,您可以使用JSCC Parser Generator 编写自己的搜索语法。
2。仅使用复杂查询
您可以单独使用 ComplexQueries 中使用的 parse
、serialize
和 query
方法。查看示例页面link as above,了解它是如何工作的。
基本上,您需要将要搜索的数据作为对象列表提供,并且您的查询必须被序列化。然后只需调用:
var result = jIO.ComplexQueries.query(query, object_list);
当然,您需要一些地方来保存可搜索的数据,所以我可能会使用 localStorage。
3.在 localStorage 之上添加 indexStorage 您可以像这样在 localStorage 之上添加索引:
mySearchFiles = JIO.newJio(
"type": "indexed",
"indices": [
"name":"index_name", "fields":["field_to_be_indexed_1"],
"name":"index_name2", "fields":["field_to_be_indexed_1","field_to_be_indexed_2"]
],
"field_types":
"field_to_be_indexed_1": "string",
"field_to_be_indexed_2": "string"
,
"sub_storage":
"type": "local",
"username": "whatever",
"application_name": "fulltextsearch"
);
这将为您添加到本地存储的所有文档创建一个索引,这将允许您在使用 complexQueries 挖掘所有文件之前对文件进行关键字搜索。所以:
mySearchFiles.put(
"_id": "your_id",
"search_result_string": "page_title/page_filename",
"index_field": "keyword",
"index_field2": "another_keyword",
"searchable_text": "your_text_to_be_searched_goes_here",
function (err, response)
// console.log(response) =
//
// "ok": true,
// "id": "your_id",
//
);
您可以调用相同的方法,但 JIO 将始终尝试先查询索引以构建结果。实际上,这更适用于远程存储位置(在来自... S3 的 HTTP 请求文件之前搜索索引),但仍然可能可用。
如果您有任何问题,请告诉我。
【讨论】:
【参考方案3】:听起来您的 html 文件是静态的,如果是这种情况,您实际上还可以有一个 json 文件,其中包含每个 html 文件中的文本。
例如,假设您有两个 html 页面,foo.html 和 bar.html,然后您可以从每个页面中提取相关内容并创建一个包含以下内容的 json 文件:
[
"id": "foo.html",
"text": "whatever text is in foo.html"
,
"id": "bar.html",
"text": "whatever text is in bar.html"
]
这将存在于您的 html 所在的目录中,例如
- project_dir
-- foo.html
-- bar.html
-- index.json
然后就可以使用带有lunr.js的索引文件了。
实际构建 index.json 文件的方式取决于可用的工具,尽管类似于 boilerpipe 或可读性。这里讨论了更多选项http://readwrite.com/2011/03/19/text-extraction
【讨论】:
以上是关于使用 Javascript 在客户端机器上进行基于全文的搜索的主要内容,如果未能解决你的问题,请参考以下文章
两个 JVM 进程可以使用 ZeroMQ 在同一台机器上进行通信吗?