用于搜索引擎样式搜索的 JavaScript 库?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11832591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript library for search engine style searching?
提问by Jordan
Is there a JavaScript library that can determine if a string matches a search query? It should be efficient and provide advanced query functionality like that of Google or LexisNexis (things like and/or operators, synonyms, and parentheses). Any kind of advanced search features would be great; it doesn't have to be an exact match to any particular search engine.
是否有可以确定字符串是否与搜索查询匹配的 JavaScript 库?它应该是高效的,并提供像 Google 或 LexisNexis 那样的高级查询功能(例如和/或运算符、同义词和括号)。任何类型的高级搜索功能都会很棒;它不必与任何特定搜索引擎完全匹配。
Motivation: I have an HTML page with a search box followed by a bunch of paragraphs (which have unique ids and are generated from a JavaScript array). When the user types a search query in the box and presses enter, all paragraphs should be hidden (i.e. their display
set to none
) if they don't match the query.
动机:我有一个带有搜索框的 HTML 页面,后面跟着一堆段落(它们具有唯一的 id 并且是从 JavaScript 数组生成的)。当用户在框中键入搜索查询并按 Enter 键时,如果所有段落与查询不匹配,则应隐藏所有段落(即display
设置为none
)。
My current strategy (using jQuery):
我目前的策略(使用 jQuery):
- Separate the query string into an array of keywords by splitting it over whitespace.
- Hide all paragraphs with
$('p').hide()
. - For each keyword, show a paragraph containing it with
$('p:contains("'+keyword+'")').show()
.
- 通过将查询字符串拆分为空格将查询字符串拆分为关键字数组。
- 用 隐藏所有段落
$('p').hide()
。 - 对于每个关键字,显示一个包含它的段落
$('p:contains("'+keyword+'")').show()
。
Which is an extremely limited search feature that is case-sensitive, treats all keywords as optional, and doesn't provide operators like and
, or
, or parentheses. It's also inefficient because it goes through each string once for each keyword even if it has already been matched.
这是一个非常有限的搜索功能,是区分大小写的,把所有的关键字为可选,并没有提供像运营商and
,or
或小括号。它也是低效的,因为即使它已经匹配,它也会为每个关键字遍历每个字符串一次。
回答by turtlemonvh
Here are some libraries that I am evaluating for projects (in July 2013). Any of these should be able to provide the core of the search feature.
以下是我正在为项目评估的一些库(2013 年 7 月)。其中任何一个都应该能够提供搜索功能的核心。
- http://lunrjs.com/
- stemming, scoring built in
- 13.8 kb minified
- updated recently (https://github.com/olivernn/lunr.js/commits/master)
- 10 contributors
- no external dependencies
- http://fusejs.io(formerly at http://kiro.me/projects/fuse.html)
- fuzzy search
- 1.58 kb minified
- updated recently (https://github.com/krisk/Fuse/commits/master)
- 1 contributor
- no external dependencies
- http://reyesr.github.io/fullproof/
- uses html5 storage with graceful degradation
- 459 kb minified
- last updated 2013 (https://github.com/reyesr/fullproof/commits/master)
- 2 contributors
- no external dependencies
- http://eikes.github.io/facetedsearch/
- pagination, templating built in
- 5.70 kb minified
- last updated 2014 (https://github.com/eikes/facetedsearch/commits/master)
- 1 contributor
- depends on jquery and underscore
- http://lunrjs.com/
- 词干,内置评分
- 13.8 kb 缩小
- 最近更新(https://github.com/olivernn/lunr.js/commits/master)
- 10 位贡献者
- 没有外部依赖
- http://fusejs.io(以前位于http://kiro.me/projects/fuse.html)
- 模糊搜索
- 1.58 kb 缩小
- 最近更新(https://github.com/krisk/Fuse/commits/master)
- 1 位贡献者
- 没有外部依赖
- http://reyesr.github.io/fullproof/
- 使用优雅降级的 html5 存储
- 459 kb 缩小
- 最后更新 2013 ( https://github.com/reyesr/fullproof/commits/master)
- 2 贡献者
- 没有外部依赖
- http://eikes.github.io/facetedsearch/
- 分页,内置模板
- 5.70 kb 缩小
- 最后更新 2014 ( https://github.com/eikes/facetedsearch/commits/master)
- 1 位贡献者
- 取决于 jquery 和下划线
If you feel like building your own, here are implementations of 2 common stemming algorithms to get you started:
如果您想构建自己的,这里有 2 种常见的词干提取算法的实现来帮助您入门:
As for handling boolean logic search operators, maybe this question about js query parserswill be useful.
至于处理布尔逻辑搜索运算符,也许这个关于 js 查询解析器的问题会有用。
回答by yamsalm
The best (easy and good) way is to use a Vector Search Algorithm.
最好(简单又好)的方法是使用矢量搜索算法。
First take all words in each paragraph and save them in a vector object (how to build explained later) and compare relation to query Vector of each Paragraph Vector
首先将每个段落中的所有单词保存在一个向量对象中(如何构建稍后解释)并比较每个段落向量的查询向量的关系
Then on each word use the Porter stemmerto make it cluster things like kid and kids.
然后在每个单词上使用Porter 词干分析器将其聚类为 Kid 和 kids 之类的东西。
var Vector = function(phar) {
var self = this;
self.InitVector = function () {
var wordArray = self.spltwords(phar);
self.VectorSize = wordArray .length;
var stemdWordArray = self.runPotterStemmer(wordArray);
self.VectoData = self.GroupAndCountWords(stemdWordArray) ;
}
self.VectoData = {};
self.runPotterStemmer = function(arr){
// run potter as seen in link
}
self.spltwords= function(arr) {
// run split
}
self.GroupAndCountWords = function(arr) {
for (var i=0; i<arr.length; i++) {
if (VectoData[arr[i]] === undefined) {
VectoData[arr[i]] = 0;
} else {
VectoData[arr[i]] = VectoData[arr[i]] +1;
}
}
}
self.compare = function(queryVector) {
// compare queryVector to current vector and return a similarity number
// number of similar words count in query divided by the length of paragraph
}
self.InitVector()
return self;
回答by yamsalm
Disclaimer - I am an author.
免责声明 - 我是作者。
You can also try ItemsJS. This is a search engine in JavaScript which supports full text, faceting and sorting.
你也可以试试 ItemsJS。这是一个 JavaScript 搜索引擎,支持全文、分面和排序。
Below you will find an interactive example - ItemsJS + VueJS:
你会在下面找到一个交互式示例 - ItemsJS + VueJS:
var configuration = {
searchableFields: ['title', 'tags', 'actors'],
sortings: {
name_asc: {
field: 'name',
order: 'asc'
}
},
aggregations: {
tags: {
title: 'Tags',
size: 10
},
actors: {
title: 'Actors',
size: 10
},
genres: {
title: 'Genres',
size: 10
}
}
}
// the rows comes from external resources
// https://github.com/itemsapi/itemsapi-example-data/blob/master/jsfiddle/imdb.js
itemsjs = itemsjs(rows, configuration);
var vm = new Vue({
el: '#el',
data: function () {
// making it more generic
var filters = {};
Object.keys(configuration.aggregations).map(function(v) {
filters[v] = [];
})
return {
query: '',
// initializing filters with empty arrays
filters: filters,
}
},
methods: {
reset: function () {
var filters = {};
Object.keys(configuration.aggregations).map(function(v) {
filters[v] = [];
})
this.filters = filters;
this.query = '';
}
},
computed: {
searchResult: function () {
var result = itemsjs.search({
query: this.query,
filters: this.filters
})
return result
}
}
});
<script src="https://cdn.rawgit.com/itemsapi/itemsapi-example-data/master/jsfiddle/imdb.js"></script>
<script src="https://cdn.rawgit.com/itemsapi/itemsjs/master/dist/itemsjs.js"></script>
<script src="https://cdn.jsdelivr.net/vue/latest/vue.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div id="el">
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#" v-on:click="reset()">ItemsJS movies</a>
</div>
<div id="navbar">
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" v-model="query" class="form-control" placeholder="Search">
</div>
</form>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container" style="margin-top: 50px;">
<h1>List of items ({{ searchResult.pagination.total }})</h1>
<p class="text-muted">Search performed in {{ searchResult.timings.search }} ms, facets in {{ searchResult.timings.facets }} ms</p>
<div class="row">
<div class="col-md-2 col-xs-2">
<div v-for="facet in searchResult.data.aggregations">
<h5 style="margin-bottom: 5px;"><strong style="color: #337ab7;">{{ facet.title }}</strong></h5>
<ul class="browse-list list-unstyled long-list" style="margin-bottom: 0;">
<li v-for="bucket in facet.buckets">
<div class="checkbox block" style="margin-top: 0; margin-bottom: 0;">
<label>
<!--<input class="checkbox" type="checkbox" v-on:click="updateFilters(facet.name, bucket.key)" v-model="filters[bucket.key]" value="{{ bucket.key }}" v-bind:value="isChecked2()">-->
<!--<input class="checkbox" type="checkbox" v-on:click="updateFilters(facet.name, bucket.key)" v-model="filters[bucket.key]" v-bind:value="bucket.key">-->
<input class="checkbox" type="checkbox" v-model="filters[facet.name]" v-bind:value="bucket.key">
{{ bucket.key }} ({{ bucket.doc_count }})
</label>
</div>
</li>
</ul>
</div>
</div>
<div class="col-md-10 col-xs-10">
<div class="breadcrumbs"></div>
<div class="clearfix"></div>
<!--<h3>List of items ({{ searchResult.pagination.total }})</h3>-->
<table class="table table-striped">
<tbody>
<tr v-for="item of searchResult.data.items">
<td><img style="width: 100px;" v-bind:src="item.image"></td>
<td></td>
<td>
<b>{{ item.name }}</b>
<br />
{{ item.description }}
</td>
<td></td>
<td>
<span style="font-size: 12px; display: block; float: left; background-color: #dbebf2; border-radius: 5px; padding: 1px 3px 1px 3px; margin: 2px;" v-for="tag in item.tags">{{ tag }}</span>
</td>
</tr>
</tbody>
</table>
<div class="clearfix"></div>
</div>
<div class="clearfix" style="margin-bottom: 100px;"></div>
</div>
</div>
</div>
回答by Fergie
I have worked on a few open source javascript projects in the search and NLP space. You could checkout search-index
which seems to be close to what you are looking for.
我在搜索和 NLP 领域从事过一些开源 javascript 项目。您可以结帐search-index
似乎与您要查找的内容很接近。
回答by phyatt
PEG.js and boolean-search.js are both useful libraries for getting some parsing libraries.
PEG.js 和 boolean-search.js 都是获取一些解析库的有用库。
https://www.npmjs.com/package/boolean-parser
https://www.npmjs.com/package/boolean-parser
https://www.npmjs.com/browse/keyword/lucene
https://www.npmjs.com/browse/keyword/lucene
Hope that helps.
希望有帮助。