Библиотека JavaScript для поиска стиля поисковой системы?

Есть ли библиотека JavaScript, которая может определить, соответствует ли строка поисковому запросу? Он должен быть эффективным и обеспечивать расширенные функции запроса, такие как Google или LexisNexis (такие вещи, как и/или операторы, синонимы и круглые скобки). Любые расширенные функции поиска были бы замечательными; он не должен быть точным совпадением с какой-либо конкретной поисковой системой.

Мотивация. У меня есть страница HTML с полем поиска, за которым следует куча абзацев (которые имеют уникальные идентификаторы и генерируются из массива JavaScript). Когда пользователь вводит поисковый запрос в поле и нажимает клавишу ввода, все абзацы должны быть скрыты (т.е. Их display установлен на none), если они не соответствуют запросу.

Моя текущая стратегия (с использованием jQuery):

  • Разделите строку запроса на массив ключевых слов, разделив ее на пробелы.
  • Скрыть все абзацы с помощью $('p').hide().
  • Для каждого ключевого слова покажите абзац, содержащий его с $('p:contains("'+keyword+'")').show().

Это чрезвычайно ограниченная функция поиска, чувствительная к регистру, рассматривает все ключевые слова как необязательные и не предоставляет такие операторы, как and, or или круглые скобки. Он также неэффективен, потому что он проходит каждую строку один раз для каждого ключевого слова, даже если он уже сопоставлен.

Ответ 1

Вот некоторые библиотеки, которые я оцениваю для проектов (в июле 2013 года). Любой из них должен быть в состоянии обеспечить ядро ​​функции поиска.

Если вам кажется, что вы строите свои собственные, вот реализация двух общих алгоритмов генерации, чтобы вы начали:

Что касается обработки операторов поиска логической логики, возможно, этот вопрос о парсерах js-запросов будет полезен.

Ответ 2

лучший (простой и удобный) способ использовать векторный поиск Algoritm

сначала взять все слова в каждом паграграфе и сохранить их в векторном объекте (как объяснять позже)

и сравнить отношение к запросу Vector каждого векторного вектора

на каждом слове используйте стример Poter, чтобы сделать его кластером вещей, таких как ребенок и дети.

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;

Ответ 3

Я работал над несколькими проектами javascript с открытым исходным кодом в пространстве поиска и NLP. Вы можете проверить search-index, который, кажется, близок к тому, что вы ищете.

Ответ 4

Отказ от ответственности - я автор.

Вы также можете попробовать ItemJS. Это поисковая система в 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>