用于搜索引擎样式搜索的 JavaScript 库? [关闭]

Posted

技术标签:

【中文标题】用于搜索引擎样式搜索的 JavaScript 库? [关闭]【英文标题】:JavaScript library for search engine style searching? [closed] 【发布时间】:2012-08-03 16:17:02 【问题描述】:

是否有可以确定字符串是否与搜索查询匹配的 javascript 库?它应该是高效的,并提供类似于 Google 或 LexisNexis 的高级查询功能(诸如和/或运算符、同义词和括号之类的东西)。任何一种高级搜索功能都会很棒;它不必与任何特定的搜索引擎完全匹配。

动机:我有一个带有搜索框的 html 页面,后面跟着一堆段落(它们具有唯一的 id,并且是从 JavaScript 数组生成的)。当用户在框中键入搜索查询并按 Enter 键时,如果所有段落与查询不匹配,则应隐藏所有段落(即它们的 display 设置为 none)。

我目前的策略(使用 jQuery):

    通过将查询字符串分隔在空格上,将其分隔为关键字数组。 隐藏所有带有$('p').hide()的段落。 对于每个关键字,用$('p:contains("'+keyword+'")').show() 显示包含它的段落。

这是一项极其有限的搜索功能,它区分大小写,将所有关键字视为可选关键字,并且不提供 andor 或括号等运算符。这也是低效的,因为它为每个关键字遍历每个字符串一次,即使它已经匹配。

【问题讨论】:

为了不区分大小写,您可以将关键字转换为小写并检查匹配,即关键字.toLowerCase() 【参考方案1】:

最好的(简单而好的)方法是使用向量搜索算法。

首先将每个段落中的所有单词保存在一个向量对象中(如何构建稍后解释)并比较每个段落向量的查询向量的关系

然后在每个单词上使用Porter stemmer 使其聚集像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;

【讨论】:

【参考方案2】:

以下是我正在为项目评估的一些库(2013 年 7 月)。其中任何一个都应该能够提供搜索功能的核心。

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 和下划线

如果您想自己构建,这里有 2 种常见的词干提取算法的实现可以帮助您入门:

https://github.com/fortnightlabs/snowball-js http://tartarus.org/martin/PorterStemmer/

至于处理布尔逻辑搜索运算符,this question about js query parsers 可能会有用。

【讨论】:

感谢分享,我想知道您是否已决定在 2017 年添加任何改进的解决方案? @Noitidart 我已经有一段时间不需要这些系统了,但如果我今天要做某事,我的第一选择仍然是当时是:lunrjs 如果您需要预览功能 Lunr.js 仍然是 2020 年 8 月要走的路。FlexSearch.js 是一个新的竞争者,但在撰写本文时缺少获得匹配位置的功能这使得它不适合实现预览功能。 Fuse.js 总是支持这一点,但它似乎更针对像书名这样的短字符串而不是文本段落——在它的默认配置中,它只能匹配从字符串开头不超过 100 个字符的单词。 惊人的图书馆收藏。非常感谢!我一直在我的项目中使用 Lunr,到目前为止,它已经产生了最好的结果并且使用起来很舒服。【参考方案3】:

免责声明 - 我是作者。

你也可以试试 ItemsJS。这是一个支持全文、分面和排序的 JavaScript 搜索引擎。

您将在下面找到一个交互式示例 - 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>

【讨论】:

【参考方案4】:

我在搜索和 NLP 领域从事过一些开源 javascript 项目。 You could checkout search-index 似乎与您要查找的内容很接近。

【讨论】:

【参考方案5】:

PEG.js 和 boolean-search.js 都是获取一些解析库的有用库。

https://pegjs.org/

https://www.npmjs.com/package/boolean-parser

https://www.npmjs.com/browse/keyword/lucene

希望对您有所帮助。

【讨论】:

以上是关于用于搜索引擎样式搜索的 JavaScript 库? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

用于匹配字典中单词的 JavaScript 算法

推荐用于 JQuery 的 JavaScript HTML 模板库? [关闭]

Android开源库:手把手教你实现一个简单好用的搜索框(含历史搜索记录)

柯南搜索和下载不适用于虚拟 Artifactory 存储库

工作笔记——搜索结果页面样式方面的Bug,以及修改

html和css制作一个搜索框,要内容与搜索图标结合,该怎么做?