2012-08-06 44 views
16

是否有JavaScript庫可以確定字符串是否與搜索查詢匹配?它應該是高效的,並提供諸如Google或LexisNexis(諸如和/或操作符,同義詞和括號之類的)的高級查詢功能。任何類型的高級搜索功能都會很棒;它不必與任何特定的搜索引擎完全匹配。用於搜索引擎風格搜索的JavaScript庫?

動機:我有一個帶搜索框的HTML頁面,後面跟着一堆段落(它們具有唯一的ID並從JavaScript數組中生成)。當用戶在框中鍵入搜索查詢並按下回車鍵時,如果所有段落與查詢不匹配,則應隱藏所有段落(即它們的display設置爲none)。

我(使用jQuery)目前的策略:查詢字符串成以上空格分割它的關鍵字的陣列

  1. 獨立。
  2. $('p').hide()隱藏所有段落。
  3. 對於每個關鍵字,顯示一個包含它的段落$('p:contains("'+keyword+'")').show()

這是一個非常有限的搜索功能,是區分大小寫的,把所有的關鍵字爲可選,並且不提供運營商如andor或小括號。這也是低效率的,因爲即使它已經被匹配,每個關鍵字每個字符串都會經過一次。

+0

爲了區分大小寫,您可以將關鍵字轉換爲小寫,並檢查匹配項i,e。 keyword.toLowerCase() – Shreedhar 2012-08-06 17:00:01

回答

27

下面是一些我正在評估項目的圖書館(2013年7月)。其中任何一種都應該能夠提供搜索功能的核心。

如果你覺得像建設自己的,這裏有2種共同的詞幹提取算法的實現,讓你開始:

至於處理布爾邏輯搜索操作符,也許this question about js query parsers將有用。

+0

感謝分享這個,我想知道你是否已經安定下來,如果你有任何改進的解決方案在2017年添加? – Noitidart 2017-07-09 20:18:38

+2

@Noitidart我在一段時間內並沒有對這些系統的需求,但是如果我今天要做些什麼,我的第一選擇仍然會和當時一樣:lunrjs – turtlemonvh 2017-07-10 22:08:18

+0

謝謝@Turtlemonvh我欣賞它! – Noitidart 2017-07-10 22:08:52

2

最好的(簡單且有效的)方法是使用矢量搜索Algoritm

先在每個pahregraph 所有單詞,並將它們保存在一個矢量對象(如何builed後面解釋)

和比較相對於查詢的每個Pargraph矢量

載體上的每個字用波特stemer,使它象孩子集羣的東西,孩子們

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]] === undefine) 
       { 
        VectoData[arr[i]] = 0;  
       } 
       else{ 
        VectoData[arr[i]] = VectoData[arr[i]] +1;   
       } 

      } 
    } 
self.compare = function(queryVector){ 
    // compare  queryVector to current vector and return a simlarty number 
    // number of simeler words counr in query divided by the length of phargrafh      
}       
self.InitVector() 
return self; 
+0

JS中的詞幹程序https://github.com/jedp/porter-stemmer – yamsalm 2012-08-08 12:05:54

1

聲明 - 我是作者。

您還可以嘗試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>