Библиотека 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>