typeahead rails 3自动完成与用户的每个请求

时间:2018-03-21 22:44:36

标签: ruby-on-rails ruby ruby-on-rails-3 jquery-ui-autocomplete typeahead

  

该应用程序使用typeahead和bootstrap 3作为自动完成功能。   但现在我们有这么多记录,它变得非常慢。

   var substringMatcher = function(strs) {
        return function findMatches(q, cb) {
            var matches, substrRegex;

            // an array that will be populated with substring matches
            matches = [];

            // regex used to determine if a string contains the substring `q`
            substrRegex = new RegExp(q, 'i');

            // iterate through the pool of strings and for any string that
            // contains the substring `q`, add it to the `matches` array
            $.each(strs, function(i, str) {
                if (substrRegex.test(str)) {
                    // the typeahead jQuery plugin expects suggestions to a
                    // JavaScript object, refer to typeahead docs for more info
                    matches.push({ value: str });
                }
            });

            cb(matches);
        };
    };
$('.typeahead').each(function(elem) {
        $(elem).typeahead({
            hint: false,
            highlight: true,
            minLength: 3
        }, {
            displayKey: 'value',
            source: substringMatcher($(elem).data('source'))
        });
    });
  

这些是app使用的typeahead功能的javasxript部分

在表单的视图一侧

<div class="form-group">
        <label class="col-sm-2 control-label" for="typeahead_book">Title</label>
        <div class="col-sm-3">
        <input value="<%=@option.book.try(:title)%>" name="option[book_title]" type="text" class="form-control typeahead typeahead-remote-book" id="typeahead_book"  data-provide="typeahead" data-items="10" data-source='<%=@book_titles%>'>
          <p class="help-block"><small><%= $autocomplete_message %></small></p>
        </div>

我使用回调

before_filter :get_autocomplete_lists, only: [:new, :edit]

def get_autocomplete_lists

    @book_titles = Rails.cache.fetch("booktitles", :force => true, expires_in: 10.minutes) do 
      Book.scoped.map(&:title)
    end


    @publisher_names = Rails.cache.fetch("publishernames", :force => true, expires_in: 10.minutes) do 
      Publisher.all.map(&:name)
    end


    @users_by_email_name = Rails.cache.fetch("users",  :force => true, expires_in: 7.days) do 
      User.scoped.map{|user| "#{user.email} - #{user.name}"}
    end 


    @country_names = Rails.cache.fetch("countrynames",  :force => true, expires_in: 7.days) do
      Country.all.map(&:first).sort
    end
    # @languages = LanguageList::COMMON_LANGUAGES.map(&:name)
    # @country_names = Anatolialit::Country::List.sort
    # 

    @languages = Rails.cache.fetch("languages",  :force => true, expires_in: 7.days) do 
      Anatolialit::Language::EnList.sort
    end

  end
  

在生成本书源代码的控制器上,如@book_titles,   应用程序正在运行但是我必须重构性能问题的代码。因为在10k记录之后@book_titles 非常大。   

<小时/>    比我干的   我在应用程序控制器

上创建了一个新的控制器操作
def book_titles
     searchterm = (params[:title])
     books =Book.any_of({ :title => /.*#{searchterm}.*/ })
     respond_to do |format|
      format.json { render json: books.map(&:title)  }
     end
  end
  

我定义了一个用作应用程序控制器的路由作为api服务

get 'booktitles/:title' => 'application#book_titles', format: :json
  

现在当我使用localhost时:3000 / booktitles / the   它将我作为json数据带给我所有标题中标有“the”的书籍。   我认为一切都可以。关于重构。   

<小时/>   但是当我按照下面的代码使用此代码时,每个请求采购先行

$(document).ready(function() {
  $('.typeahead-remote-book').typeahead({
      source: function (query, process) {
          return $.get('/booktitles', { query: query }, function (data) {
              return typeahead.process(data);
          });
      }
  });
});
  

我将表单的视图部分更改为

<div class="form-group">
        <label class="col-sm-2 control-label" for="typeahead_book">Title</label>
        <div class="col-sm-3">
        <input value="<%=@option.book.try(:title)%>" name="option[book_title]" type="text" class="form-control typeahead typeahead-remote-book" id="typeahead_book"  data-provide="typeahead" data-items="10" >
          <p class="help-block"><small><%= $autocomplete_message %></small></p>
        </div>
      </div>

*我不知道情况有什么问题,但它不起作用*

你可以帮帮我吗?关于解决问题。 谢谢你的帮助.. 最好的祝福。

1 个答案:

答案 0 :(得分:2)

问题是您是否正在尝试在数据库中进行实时搜索,而且效率不高。至少要确保你在标题上索引书籍。您应该进行以下迁移:

class AddIndexOnBookTitles < ActiveRecord::Migration
  def change
    add_index :books, :title, unique: false #or omit false if dupes not allowed.
  end
end

然后你不想要书籍对象,而只需要标题,你应该把它们缓存到某个地方。我们可以稍后讨论。

不要在.map对象上使用ActiveRecordRelation,而是.pluck只需从数据库中提取所需的字段。

def book_titles
  books = Book.any_of({ :title => /.*#{params[:title]}.*/ }).pluck(:title)
  respond_to do |format|
    format.json { render json: books }
  end
end

如果你有很多书,那可能会很慢。但首先尝试一下,看看它是否更好。如果没有,我们需要进行一些缓存,或者使用专为此类事物设计的Elasticsearch。