- 浏览: 2678414 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
80后的童年2:
深入浅出MongoDB应用实战开发网盘地址:https://p ...
MongoDB入门教程 -
shliujing:
楼主在不是精通java和php的前提下,请不要妄下结论。
PHP、CakePHP哪凉快哪呆着去 -
安静听歌:
希望可以一给一点点注释
MySQL存储过程之代码块、条件控制、迭代 -
qq287767957:
PHP是全宇宙最强的语言!
PHP、CakePHP哪凉快哪呆着去 -
rryymmoK:
深入浅出MongoDB应用实战开发百度网盘下载:链接:http ...
MongoDB入门教程
Ferret是Ruby的文本搜索引擎,它基于Apache Lucene
安装Ferret非常简单:
Ferret是一堆C代码的Ruby代码封装,Ferret是针对Ruby的而不是RoR的
而Acts As Ferret则是针对RoR的
我们有两种方式安装Acts As Ferret:
1,以gem方式安装
然后在environment.rb里添加
2,以plugin方式安装
(虽然推荐以插件方式安装acts_as_ferret,但貌似这样安装不起作用,svn地址改为acts_as_ferret也不行,再议)
先看一个简单的例子,我们先给需要做index的model加上如下代码:
然后假如我们做如下search;
这将发生如下事情:
1,在Rails程序目录下创建/index/development/member子目录,所有的index文件将在这里创建
2,Members的first/last name将加入到该index,以后每次add/update/delete一个member都会增量更新index
如果你需要重新生成index,只需删除相应的文件目录并重启服务器,下次search时就会重新生成index
3,ActsAsFerret将会在我们的index上调用Ferret的search_each方法
4,我们将得到10条如下形式的结果:
我们得到每个member的id和search score
即使有超过10条的结果,我们默认将只能得到10条返回的结果
Options
1,offset,默认为0
2,limit,默认为10,:all将返回所有结果
3,sort
如果我们需要查询结果的数量
或者这样做
如果我们需要查询结果为model
我们有更好的办法,find_by_contents
这将做如下事情:
1,首先使用find_id_by_contents得到ids
2,使用返回的ids来查询Model
3,返回ActsAsFerret::SearchResults对象Array(可以认为是ActiveRecord对象,但是多一些额外的特性)
我们可以做如下的事情
注意total_hits和ferret_score就是额外的特性
对搜索结果分页
1,对你的model加上如下方法
修改application.rb
然后修改controller
在view中的代码
查询字符串
1,搜索"Gregg Pollack"将返回在ANY域中以ANY顺序排列的包含"Gregg"和"Pollack"的结果
2,搜索"Gregg OR Pollack"将返回包含"Gregg"或"Pollack"的结果
3,搜索"Gregg~"模糊查询,将返回包含"Gregg"的结果
4,搜索"first_name:Gregg"将返回first name为"Gregg"的结果
5,搜索"+first_name:Gregg -last_name:Jones"将返回first name为"Gregg"并且last name不是"Jones"的结果
更复杂的查询条件参考Apache Lucene Parser Syntax
搜索多个表
也就是说我们可以搜索model方法返回的任何东西,甚至是tags
排序
假如我们需要对title搜索并对title排序,但是排序的field要求不能被index和search,我们可以这样做
然后我们可以在controller里按title排序搜索了
存储数据
默认情况下acts_as_ferret只对数据做index而不存储数据,如果数据很小,我们可以这样做来在index里存储数据来加快search数据
我们给model添加如下search方法
这样我们根本就不用接触数据库就可以查询数据,view代码
Highlighting
我们来看看怎样用ferret做出Google搜索结果bold关键字的效果
前提是上面所说存储搜索的fields
我们修改上面的search方法
使用Boost
如果我们希望对title的搜索结果的score要比author的搜索结果的score稍高,我们可以使用boost参数
但是boost参数只能提高score,而不能分开title和author的搜索结果
Production环境下使用
由于性能问题,Production环境下最好以DRb Server的形式运行
注:本文参考Acts_As_Ferret Tutorial
安装Ferret非常简单:
gem install ferret
Ferret是一堆C代码的Ruby代码封装,Ferret是针对Ruby的而不是RoR的
而Acts As Ferret则是针对RoR的
我们有两种方式安装Acts As Ferret:
1,以gem方式安装
gem install acts_as_ferret
然后在environment.rb里添加
require 'acts_as_ferret'
2,以plugin方式安装
ruby script/plugin install svn://projects.jkraemer.net/acts_as_ferret/tags/stable/acts_as_ferret
(虽然推荐以插件方式安装acts_as_ferret,但貌似这样安装不起作用,svn地址改为acts_as_ferret也不行,再议)
先看一个简单的例子,我们先给需要做index的model加上如下代码:
class Member < ActiveRecord::Base acts_as_ferret :field => [:first_name, :last_name] end
然后假如我们做如下search;
members = Member.find_id_by_contents("Gregg")
这将发生如下事情:
1,在Rails程序目录下创建/index/development/member子目录,所有的index文件将在这里创建
2,Members的first/last name将加入到该index,以后每次add/update/delete一个member都会增量更新index
如果你需要重新生成index,只需删除相应的文件目录并重启服务器,下次search时就会重新生成index
3,ActsAsFerret将会在我们的index上调用Ferret的search_each方法
4,我们将得到10条如下形式的结果:
members = [ {:model => "Member", :id => "4", :score => "1.0"}, {:model => "Member", :id => "4", :score => "0.93211"}, {:model => "Member", :id => "4", :score => "0.32212"}, ... ]
我们得到每个member的id和search score
即使有超过10条的结果,我们默认将只能得到10条返回的结果
Options
1,offset,默认为0
2,limit,默认为10,:all将返回所有结果
3,sort
如果我们需要查询结果的数量
total_results = Member.total_hits("Gregg")
或者这样做
results = [] total_results = Member.find_id_by_contents("Gregg") { |result| results.push result }
如果我们需要查询结果为model
results = [] total_results = Member.find_id_by_contents("Gregg") { |result| results.push Member.find(result[:id]) }
我们有更好的办法,find_by_contents
@results = Member.find_by_contents("Gregg")
这将做如下事情:
1,首先使用find_id_by_contents得到ids
2,使用返回的ids来查询Model
3,返回ActsAsFerret::SearchResults对象Array(可以认为是ActiveRecord对象,但是多一些额外的特性)
我们可以做如下的事情
members = Member.find_by_contents("Gregg") # It gives us total hits! puts "Total hits = #{members.total_hits}" for member in members puts "#{member.first_name} #{member.last_name}" # And the search Score! puts "Search Score = #{member.ferret_score}" end
注意total_hits和ferret_score就是额外的特性
对搜索结果分页
1,对你的model加上如下方法
def self.full_text_search(q, options = {}) return nil if q.nil? or q=="" default_options = {:limit => 10, :page => 1} options = default_options.merge options # get the offset based on what page we're on options[:offset] = options[:limit] * (options.delete(:page)to_i-1) # now do the query with our options results = Member.find_by_contents(q, options) return [results.total_hits, results] end
修改application.rb
def pages_for(size, options = {}) default_options = {:per_page => 10} options = default_options.merge options pages = Paginator.new self, size, options[:per_page], (params[:page]||1) return pages end
然后修改controller
def search @query = params[:query] @total, @members = Member.full_text_search(@query, :page => (params[:page]||1)) @pages = pages_for(@total) end
在view中的代码
<%= link_to 'Previous page', { :page => @pages.current.previous, :query => @query } if @pages.current.previous %> <%= pagination_links(@pages, :params => { :query => @query }) %> <%= link_to 'Next page', { :page => @pages.current.next, :query => @query } if @pages.current.next %>
查询字符串
1,搜索"Gregg Pollack"将返回在ANY域中以ANY顺序排列的包含"Gregg"和"Pollack"的结果
2,搜索"Gregg OR Pollack"将返回包含"Gregg"或"Pollack"的结果
3,搜索"Gregg~"模糊查询,将返回包含"Gregg"的结果
4,搜索"first_name:Gregg"将返回first name为"Gregg"的结果
5,搜索"+first_name:Gregg -last_name:Jones"将返回first name为"Gregg"并且last name不是"Jones"的结果
更复杂的查询条件参考Apache Lucene Parser Syntax
搜索多个表
class Book < ActiveRecord::Base acts_as_ferret :fields => [:title, :author_name] def author_name return "#{self.author.first_name} #{self.author.last_name}" end end
也就是说我们可以搜索model方法返回的任何东西,甚至是tags
class Book < ActiveRecord::Base acts_as_taggable acts_as_ferret :fields => [:title, :tags_with_spaces] def tags_with_spaces return self.tag_names.join(" ") end end
排序
假如我们需要对title搜索并对title排序,但是排序的field要求不能被index和search,我们可以这样做
acts_as_ferret :fields => { :title => {}, :tags_with_spaces => {}, :title_for_sort => {:index => :untokenized} } def title_for_sort return self.title end
然后我们可以在controller里按title排序搜索了
s = Ferret::Search::SortField.new(:title_for_sort, :reverse => false) @total, @members = Member.full_text_search(@query, {:page => (params[:page]||1), :sort => s}
存储数据
默认情况下acts_as_ferret只对数据做index而不存储数据,如果数据很小,我们可以这样做来在index里存储数据来加快search数据
acts_as_ferret :field => { :title => {:store => :yes}, :author_name => {:store => :yes} }
我们给model添加如下search方法
def self.find_storage_by_contents(query, options = {}) # Get the index that acts_as_ferret created for us index = self.ferret_index results = [] @ search_each is the core search function from Ferret, which Acts_as_ferret hides total_hits = index.search_each(query, options) do |doc, score| result = {} # Sotre each field in a hash which we can reference in our views result[:name] = index[doc][:name] result[:author_name] = idnex[doc][:author_name] # We can even put the score in the hash, nice! result[:score] = score results.push result end return block_given? ? total_hits : [ttal_hit, results] end
这样我们根本就不用接触数据库就可以查询数据,view代码
<% @results.each_with_index do |result, index| %> <%= index %>. <%= result[:name] %> by <%= result[:author_name] %> <br/> Score: <%= result[:score] %> <% end %>
Highlighting
我们来看看怎样用ferret做出Google搜索结果bold关键字的效果
前提是上面所说存储搜索的fields
我们修改上面的search方法
def find_storage_by_contents(query, options = {}) index = self.ferret_index # Get the index that acts_as_ferret created for us results = [] # search_each is the core search function from Ferret, which Acts_as_ferret hides total_hits = index.search_each(query, options) do |doc, score| result = {} # Store each field in a hash which we can reference in our views result[:name] = index.highlight(query, doc, :field => :name, :pre_tag => "<strong>", :post_tag => "</strong>", :num_excerpts => 1) result[:author_name] = index.highlight(query, doc, :field => :author_name, :pre_tag => "<strong>", :post_tag => "</strong>", :num_excerpts => 1) result[:score] = score # We can even put the score in the hash, nice! results.push result end return block_given? ? total_hits : [total_hits, results] end
使用Boost
如果我们希望对title的搜索结果的score要比author的搜索结果的score稍高,我们可以使用boost参数
acts_as_ferret :fields => { :title => {:boost => 2} :author => {:boost => 0} }
但是boost参数只能提高score,而不能分开title和author的搜索结果
Production环境下使用
由于性能问题,Production环境下最好以DRb Server的形式运行
注:本文参考Acts_As_Ferret Tutorial
评论
6 楼
heweiya
2008-07-25
首先感谢你的文章,在配置使用当中有一些难题,尤其是在做高亮的时候,请教问题如下:Highlighting 当中的修改方法:def find_storage_by_contents(query, options = {})
当中的index = self.ferret_index是个什么东东,好像没有这个ferret_index函数,是不是就是analyzer = RMMSeg::Ferret::Analyzer.new { |tokenizer|
Ferret::Analysis::LowerCaseFilter.new(tokenizer)
}
$index = Ferret::Index::Index.new(:analyzer => analyzer)
如果有源代码下载就好了,通过这个文章我学习了很多东西,但是就是在做一些配置时遇到了难题,希望博主回复这些问题.
谢谢!
当中的index = self.ferret_index是个什么东东,好像没有这个ferret_index函数,是不是就是analyzer = RMMSeg::Ferret::Analyzer.new { |tokenizer|
Ferret::Analysis::LowerCaseFilter.new(tokenizer)
}
$index = Ferret::Index::Index.new(:analyzer => analyzer)
如果有源代码下载就好了,通过这个文章我学习了很多东西,但是就是在做一些配置时遇到了难题,希望博主回复这些问题.
谢谢!
5 楼
zhangzldipan
2008-07-24
4 楼
zhangzldipan
2008-06-22
查了那么多次内容,看了那么多你的文章,没一次从你身上得到好处!真该好好检讨下!郁闷……
3 楼
hideto
2007-09-26
ferret是一个gem
2 楼
blackanger
2007-09-24
acts_as_ferret和ferret什么关系?
我没有装ferret,在用acts_as_ferret的时候报错no such file to load -- ferret,装了ferret以后才正常。acts_as_ferret是基于ferret的?
我没有装ferret,在用acts_as_ferret的时候报错no such file to load -- ferret,装了ferret以后才正常。acts_as_ferret是基于ferret的?
1 楼
sina2009
2007-09-14
不知道怎么回事,模糊查询Person.find_by_contents("an~")查询不到任何条目
Person.find_by_contents("andy")可以查询出条目
不知道有何解决方案
Person.find_by_contents("andy")可以查询出条目
不知道有何解决方案
发表评论
-
用了TextMate才知道什么叫神级Editor
2011-03-09 04:51 57961一直用Eclipse作为开发Ruby和Java项目的IDE,但 ... -
Ruby使用OAuth登录新浪微博和豆瓣
2011-01-09 12:49 4434首先需要安装oauth这个gem包 gem install ... -
使用Passenger+nginx部署Rails
2010-12-28 15:12 50111. Install Passender gem instal ... -
markItUp+rdiscount搭建Rails下可视化Markdown编辑器
2010-12-21 17:48 5447markItUp是基于jQuery的可视化编辑器,支持Html ... -
Rails3 and MongoDB Quick Guide
2010-12-10 14:13 2753Install MongoDB Download: http: ... -
基于ruby-protobuf的rpc示例
2009-08-11 11:51 41481, 安装ruby-protobuf gem instal ... -
Ruby导出xls和csv的utf-8问题的解决
2009-02-04 15:05 6839数据库数据为utf-8格式,包括中文和拉丁文等等 导出文件xl ... -
URL/HTML/JavaScript的encode/escape
2009-01-04 13:03 9324最近经常被URL、HTML、JavaScript的encode ... -
各种排序的Ruby实现
2008-11-27 14:51 3994Θ(n^2) 1, Bubble sort def bu ... -
12月5日北京RoR活动!
2008-11-26 18:38 3017又是一年过去了,Rails在国内的发展势态良好,很多使用RoR ... -
Rails程序开发的最大问题是代码规范
2008-08-28 11:56 5518使用Rails开发大型复杂B2B应用一年了,这个项目目前开发人 ... -
Web开发大全:ROR版——推荐序
2008-07-09 00:39 2416来自http://www.beyondrails.com/bl ... -
深入ActionMailer,使用Sendmail发邮件
2008-07-03 11:41 3396来自: http://www.beyondrails.com/ ... -
Rails里如何结合ExceptionNotification配置gmail账户发邮件
2008-06-19 19:56 30821,安装ExceptionNotification rub ... -
使用coderay和railscasts样式进行代码高亮
2008-06-17 00:16 2395CodeRay是一个语法高亮的Ruby库,效率很不错。 Cod ... -
Capistrano试用
2008-06-16 19:05 19581,客户端机器安装Capistrano gem insta ... -
lighttpd真垃圾啊
2008-06-04 18:38 2533使用lighttpd+fcgi跑Rails程序,文件上传会si ... -
将gem变成plugin
2008-06-04 11:27 1801有什么样的需求就有什么样的对策 当vhost上的帐号没有ge ... -
在Rails里使用ReCaptcha添加验证码
2008-06-03 15:51 42661,去http://recaptcha.net/sign up ... -
Rails里给文件上传添加progress_bar
2008-05-27 17:00 2087文件上传很慢时,UI没有什么用户提示,这样让人很费解,所以我们 ...
相关推荐
"acts_as_authenticated" 是一个经典的Ruby on Rails插件,它为Rails应用提供了用户认证功能。在Rails框架中,用户认证通常涉及验证用户身份、管理会话以及处理登录和登出等操作。acts_as_authenticated插件简化了这...
介绍插件,用于对记录进行排序(使用 gem)安装要启用rails_admin_acts_as_list,请将以下内容添加到您的Gemfile : gem 'rails_admin_acts_as_list'gem 'rails_admin' 重要提示: rails_admin_acts_as_list之前必须...
"acts_as_paranoid" 是一个在Ruby on Rails框架中常用的gem,用于处理数据库记录的软删除(soft delete)。在数据库操作中,通常我们会遇到删除数据的需求,但直接删除可能会导致数据丢失,尤其是在生产环境中。...
在Ruby on Rails框架中,`acts_as_rateable`是一个非常实用的插件,它允许用户对模型进行评分,从而实现简单的打分功能。这个插件是Rails社区中的一个开源项目,旨在简化应用中的评分系统集成。在本篇讨论中,我们将...
acts_as_nested_set是Rails社区中广泛使用的Nested Set库,而BetterNestedSet则是它的增强版,提供了更多功能和优化。本文将深入探讨BetterNestedSet的原理、用法以及相较于acts_as_nested_set的优势。 1. Nested ...
#ActsAsCategory acts_as_category (Version 2.0 beta)acts_as_category,是acts_as插件在acts_as_tree风格的Ruby on Rails的ActiveRecord的模式,但有一些额外的功能,以及多种便捷视图助手。例子(有关实例方法和...
它创建一个Comment模型,并处理该模型与您声明为可注释模型的任何模型之间的关系。 安装: 将以下行添加到您的Gemfile中 Rails gem 'acts_as_commentable' Rails gem 'acts_as_commentable' , '3.0.1' Rails ...
使徒行传 一个Rails插件来添加软删除。...用法安装gem: gem 'acts_as_paranoid' , '~> 0.7.0' bundle install创建迁移bin/rails generate migration AddDeletedAtToParanoiac deleted_at:datetime:index启用ActsAs
acts_as_restful_list 就像acts_as_list 一样,但不必使用非标准方法调用(如insert_at)来弄乱您的代码,acts_as_restful_list 使管理列表变得简单。 您可以像更新其他任何内容一样更新 position 属性,其余的都...
Api-acts_as_api.zip,使在rails中创建api响应变得简单和有趣,一个api可以被认为是多个软件设备之间通信的指导手册。例如,api可用于web应用程序之间的数据库通信。通过提取实现并将数据放弃到对象中,api简化了编程...
$ rails generate acts_as_liked 并且不要忘记迁移您的数据库 $ rake db:migrate 用法 可爱的模特 将acts_as_likeable添加到任何模型,它的实例可以被其他模型喜欢。 class Post < ActiveRecord :: Base ...
作为可评论行为(现在有评论线程(TM)!!!——在(TM)上开玩笑) 允许将线程注释添加到多个不同的模型。 与acts_as_commentable 兼容(但需要更改数据库架构) ... rails generate acts_as_commentable_with_
偏执狂将继续接受错误修复并支持Rails的新版本,但不接受新功能。 偏执狂 偏执狂是Rails 3/4/5的的重新实现,使用的代码少得多。 当您的应用程序使用偏执狂时,在ActiveRecord对象上调用destroy并不会真正破坏...
1. **无缝集成**:acts_as_xapian能够无缝地与Rails模型集成,只需在模型中添加一行`acts_as_xapian`代码,即可开启对该模型的全文搜索支持。 2. **自定义索引**:开发者可以自由决定哪些字段参与索引,甚至可以...
rails generate acts_as_aliased:install rake db:migrate 这将创建一个新表aliases 。 用法 假设您有一个需要别名的模型Company ,因为公司名称有不同的版本。 使用acts_as_aliased在模型中启用别名: model ...
acts_as_shopping_cart 一个简单的购物车实现。 您可以找到示例应用程序。 安装 滑轨3 从0.2.0版开始,不再支持Rails 3。 如果您仍需要在Rails 3应用程序中实现此gem,请使用0-1-x分支 将其包含在您的Gemfile中 ...
actions_as_nps_rateable act_as_nps_rateable为基于ActiveRecord的模型提供净促销值(NPS)评级和分析。 促销员净额是衡量客户满意度的指标; 它是会推荐您的产品/服务的客户比例与不会推荐您的产品/服务的客户...
Acts as owner 是 Ruby on Rails 的一个插件,它为所有者对象提供了自我查询可拥有对象的所有权的能力。 可拥有对象可以是属于所有者对象的任何对象和属于可拥有对象的任何对象。 属于拥有的可拥有的父代的任何可...
现在我们将这个插件从Rails2.x的版本升级到了3.x版本,并且抽取成了一个通用插件,开始应用于新的Rails3.2的项目之上。有志于AR对象缓存优化的ruby程序员不容错过。 使用方法: class User acts_as_cached(:...
《Rails101_by_rails4.0》是一本专注于Rails 4.0.0版本和Ruby 2.0.0版本的自学教程书籍,它定位于中文读者,旨在成为学习Rails框架的参考教材。Rails(Ruby on Rails)是一个采用Ruby语言编写的开源Web应用框架,它...