{"id":1716,"date":"2008-04-01T05:17:03","date_gmt":"2008-03-31T21:17:03","guid":{"rendered":"http:\/\/ihower.idv.tw\/blog\/?p=1716"},"modified":"2015-09-05T10:54:49","modified_gmt":"2015-09-05T02:54:49","slug":"fulltext-search-sphinx-on-rails","status":"publish","type":"post","link":"https:\/\/ihower.tw\/blog\/1716-fulltext-search-sphinx-on-rails","title":{"rendered":"\u5168\u6587\u641c\u5c0b Sphinx on Rails"},"content":{"rendered":"<p><a href='http:\/\/www.sphinxsearch.com\/'><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1717\" data-permalink=\"https:\/\/ihower.tw\/blog\/?p=1717\" data-orig-file=\"\" data-orig-size=\"200,51\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"sphinx\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"\" data-large-file=\"\" src=\"\/blog\/wp-content\/uploads\/2008\/04\/sphinx.jpg\" alt=\"\" title=\"sphinx\" width=\"200\" height=\"51\" class=\"alignnone size-medium wp-image-1717\" \/><\/a><\/p>\n<p>Update(2009\/3\/31): \u9664\u4e86 ultrasphinx \u4e4b\u5916\uff0c\u9084\u6709\u4e00\u5957 Ruby library \u662f <a href=\"http:\/\/ts.freelancing-gods.com\/\">thinking sphinx<\/a> \u76ee\u524d\u5df2\u7d93\u662f\u6700\u88ab\u63a8\u85a6\u7684 Rails \u5957\u4ef6\uff0c\u6211\u4e5f\u63a8\u85a6\u6539\u4f7f\u7528 thinking sphinx\uff0cpeepcode \u6709\u51fa\u5b83\u7684 <a href=\"https:\/\/peepcode.com\/products\/thinking-sphinx-pdf\">PDF<\/a>\u3002<\/p>\n<p>\u96d6\u7136\u5728 Ruby\/Rails \u5708\u6bd4\u8f03\u5e38\u807d\u5230 <a href=\"http:\/\/ferret.davebalmain.com\/\">Ferret<\/a>\uff0c\u4e0d\u904e\u9019\u96bb\u96ea\u8c82\u7684\u7a69\u5b9a\u5ea6\u4e00\u76f4\u70ba\u4eba\u6240\u8a6c\u75c5\u3002\u6211\u5728 survey Rails \u5168\u6587\u641c\u5c0b\u65b9\u6848\u7684\u6642\u5019\uff0c\u770b\u5230\u53e6\u4e00\u500b\u6709 Rails plugin \u652f\u63f4\u7684\u958b\u653e\u6e90\u78bc\u5168\u6587\u641c\u5c0b\u5f15\u64ce  <a href=\"http:\/\/www.sphinxsearch.com\/\">Sphinx<\/a>\uff0c\u642d\u914d\u7684 Rails plugin \u53eb\u505a <a href=\"http:\/\/blog.evanweaver.com\/articles\/2007\/07\/09\/ultrasphinx-searching-the-world-in-231-seconds\/\">Ultrasphinx<\/a>\u3002<\/p>\n<p>Sphinx \u7684\u7279\u9ede\u5728\u65bc\u5b83\u76f4\u63a5\u5b58\u53d6 MySQL (\u6216PostgreSQL)\uff0c\u5b8c\u5168\u7368\u7acb\u65bc Rails app\u3002\u5b83\u4e0d\u50cf <a href=\"http:\/\/projects.jkraemer.net\/acts_as_ferret\/\">acts_as_ferret<\/a> \u548c <a href=\"http:\/\/acts-as-solr.railsfreaks.com\/acts_as_solr\">acts_as_solr<\/a> \u4f7f\u7528 rails callback \u4f86\u505a\u65b0\u8cc7\u6599\u7684\u7d22\u5f15\u52d5\u4f5c\uff0c\u800c\u662f\u8a2d\u5b9a crontab \u5b9a\u671f\u8dd1 indexer (\u5982\u6bcf\u534a\u5c0f\u6642)\uff0c\u5927\u5927\u63d0\u9ad8\u4e86 search daemon \u7a69\u5b9a\u5ea6(\u53cd\u4e4b\u4ea6\u7136)\uff0c\u4e5f\u4e0d\u592a\u6709\u7d22\u5f15\u8cc7\u6599\u640d\u58de\u7684\u554f\u984c(\u5728\u8b1bferret?)\u3002\u76ee\u524d\u770b\u5230\u7684<a href=\"http:\/\/www.ruby-forum.com\/topic\/137629\">\u8a55\u50f9<\/a>\u4e5f\u90fd\u662f\u7a69\u7a69\u7a69\u9ad8\u6548\u80fd\uff0c\u7528\u904e\u5c31\u4e0d\u60f3\u518d\u7528 Ferret \u4e86\u3002Ultrasphinx \u7684\u4f5c\u8005\u4e5f\u6709 <a href=\"http:\/\/blog.evanweaver.com\/articles\/2008\/03\/17\/rails-search-benchmarks\/\">benchmark<\/a> \u6578\u64da\u53ef\u4f9b\u4f50\u8b49\u3002<\/p>\n<p><!--more--><\/p>\n<p>\u5b89\u88dd\u7b2c\u4e00\u6b65\u662f\u53bb Sphinx \u5b98\u65b9\u7db2\u7ad9\u4e0b\u8f09\u4e26 compile<\/p>\n<pre>\nwget\ntar xvf sphinx-<version>.tar.gz\ncd sphinx-<version>\n.\/configure && make && sudo make install\n<\/pre>\n<p>\u5b89\u88dd chronic gem<\/p>\n<pre>\nsudo gem install chronic\n<\/pre>\n<p>\u5b89\u88dd ultrasphinx plugin:<\/p>\n<pre>\nscript\/plugin install svn:\/\/rubyforge.org\/var\/svn\/fauna\/ultrasphinx\/trunk\n<\/pre>\n<p>\u5982\u679c\u8981\u5206\u9801\u529f\u80fd\uff0cultrasphinx \u4e5f\u6709\u652f\u63f4 <a href=\"http:\/\/errtheblog.com\/posts\/56-im-paginating-again\">will_paginate<\/a> plugin\u3002<\/p>\n<pre>\n script\/plugin install svn::\/\/errtheblog.com\/svn\/plugins\/will_paginate\n<\/pre>\n<p>\u88dd\u597d\u4e4b\u5f8c\u5c31\u4f86\u8a2d\u5b9a<\/p>\n<pre>\nmkdir config\/ultrasphinx\ncp vendor\/plugin\/ultrasphinx\/examples\/default.base config\/ultrasphinx\/\n<\/pre>\n<p>\u8a2d\u5b9a\u6a94\u7684\u90e8\u4efd\u6211\u5c31\u76f4\u63a5\u5927\u8d08\u9001\u7d66\u5404\u4f4d(\u8a18\u5f97\u6539path)\uff0c\u5305\u62ec\u652f\u63f4\u4e2d\u6587\u641c\u5c0b\uff0c\u9019\u500b\u7b54\u6848\u5728\u5b98\u7db2<a href=\"http:\/\/www.sphinxsearch.com\/forum\/view.html?id=587\">\u8a0e\u8ad6\u5340<\/a>\u6709\u3002<\/p>\n<pre>\n\nindexer\n{\n  # Indexer running options\n  mem_limit = 256M \n}\n\nsearchd\n{\n  address = 0.0.0.0\n  port = 3312\n  log = log\/searchd.log\n  query_log = log\/query.log\n  read_timeout = 5\n  max_children = 300\n  pid_file = log\/searchd.pid\n  max_matches = 100000\n}\n\nclient\n{\n  # Client options\n  # Name of the Aspell dictionary (two letters max)\n  dictionary_name = ap\n  # How your application connects to the search daemon (not necessarily the same as above)\n  server_host = localhost\n  server_port = 3312\n}\n\nsource\n{\n  # Individual SQL source options\n  sql_ranged_throttle = 0  \n  sql_range_step = 5000   \n  sql_query_post =\n}\n\nindex\n{\n  # Index building options\n  path = \/your-rails-app\/db\/sphinx\/\n  docinfo = extern # just leave this alone\n  # morphology = stem_en\n  stopwords = # \/path\/to\/stopwords.txt\n  min_word_len = 1\n\n  # HTML-specific options\n  html_strip = 0\n  html_index_attrs =\n  \n  # Enable these if you need wildcard searching. They will slow down indexing significantly.\n  min_infix_len = 1    \n  #   enable_star = 1 \n    \n  charset_type = utf-8 # or sbcs (Single Byte Character Set)\n  min_word_len = 1\n  \n  #http:\/\/www.sphinxsearch.com\/forum\/view.html?id=587  \n  charset_table = U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z,A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6, U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101, U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109, U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F, U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, U+0116->U+0117, U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D, U+011D, U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, U+0134->U+0135, U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, U+013C, U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, U+0143->U+0144, U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, U+014B, U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, U+0152->U+0153, U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159, U+0159, U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, U+0160->U+0161, U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, U+0167, U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, U+016E->U+016F, U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175, U+0175, U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, U+017B->U+017C, U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, U+0430..U+044F, U+05D0..U+05EA, U+0531..U+0556->U+0561..U+0586, U+0561..U+0587, U+0621..U+063A, U+01B9, U+01BF, U+0640..U+064A, U+0660..U+0669, U+066E, U+066F, U+0671..U+06D3, U+06F0..U+06FF, U+0904..U+0939, U+0958..U+095F, U+0960..U+0963, U+0966..U+096F, U+097B..U+097F, U+0985..U+09B9, U+09CE, U+09DC..U+09E3, U+09E6..U+09EF, U+0A05..U+0A39, U+0A59..U+0A5E, U+0A66..U+0A6F, U+0A85..U+0AB9, U+0AE0..U+0AE3, U+0AE6..U+0AEF, U+0B05..U+0B39, U+0B5C..U+0B61, U+0B66..U+0B6F, U+0B71, U+0B85..U+0BB9, U+0BE6..U+0BF2, U+0C05..U+0C39, U+0C66..U+0C6F, U+0C85..U+0CB9, U+0CDE..U+0CE3, U+0CE6..U+0CEF, U+0D05..U+0D39, U+0D60, U+0D61, U+0D66..U+0D6F, U+0D85..U+0DC6, U+1900..U+1938, U+1946..U+194F, U+A800..U+A805, U+A807..U+A822, U+0386->U+03B1, U+03AC->U+03B1, U+0388->U+03B5, U+03AD->U+03B5, U+0389->U+03B7, U+03AE->U+03B7, U+038A->U+03B9, U+0390->U+03B9, U+03AA->U+03B9, U+03AF->U+03B9, U+03CA->U+03B9, U+038C->U+03BF, U+03CC->U+03BF, U+038E->U+03C5, U+03AB->U+03C5, U+03B0->U+03C5, U+03CB->U+03C5, U+03CD->U+03C5, U+038F->U+03C9, U+03CE->U+03C9, U+03C2->U+03C3, U+0391..U+03A1->U+03B1..U+03C1, U+03A3..U+03A9->U+03C3..U+03C9, U+03B1..U+03C1, U+03C3..U+03C9, U+0E01..U+0E2E, U+0E30..U+0E3A, U+0E40..U+0E45, U+0E47, U+0E50..U+0E59, U+A000..U+A48F, U+4E00..U+9FBF, U+3400..U+4DBF, U+20000..U+2A6DF, U+F900..U+FAFF, U+2F800..U+2FA1F, U+2E80..U+2EFF, U+2F00..U+2FDF, U+3100..U+312F, U+31A0..U+31BF, U+3040..U+309F, U+30A0..U+30FF, U+31F0..U+31FF, U+AC00..U+D7AF, U+1100..U+11FF, U+3130..U+318F, U+A000..U+A48F, U+A490..U+A4CF,\n  ngram_len = 1\n  ngram_chars = U+4E00..U+9FBF, U+3400..U+4DBF, U+20000..U+2A6DF, U+F900..U+FAFF, U+2F800..U+2FA1F, U+2E80..U+2EFF, U+2F00..U+2FDF, U+3100..U+312F, U+31A0..U+31BF, U+3040..U+309F, U+30A0..U+30FF, U+31F0..U+31FF, U+AC00..U+D7AF, U+1100..U+11FF, U+3130..U+318F, U+A000..U+A48F, U+A490..U+A4CF\n}\n<\/pre>\n<p>\u63a5\u4e0b\u4f86\u8a2d\u5b9a\u4f60\u7684 Model \u8981\u7d22\u5f15\u54ea\u4e9b\u6b04\u4f4d\uff0c\u4f8b\u5982<\/p>\n<pre>\nClass Topic < ActiveRecord::Base\n  is_indexed :fields => ['subject', 'content']\nend\n<\/pre>\n<p>\u63a5\u8457\u7522\u751f\u5be6\u969b\u8981\u7528\u7684\u8a2d\u5b9a\u6a94\u3002\u6ce8\u610f\u5230\u5982\u679c\u4f60\u4e4b\u5f8c\u6709\u6539 model \u7684 is_indexed\uff0c\u9019\u500b\u8a2d\u5b9a\u6a94\u6bcf\u6b21\u90fd\u8981\u91cd\u65b0\u7522\u751f(\u56e0\u70ba\u88e1\u9762\u7684\u6771\u897f\u662f SQL \u6307\u4ee4)\u3002<\/p>\n<pre>\n  rake ultrasphinx:configure\n<\/pre>\n<p>\u8dd1\u7d22\u5f15\u8ddf daemon \u5f88\u7c21\u55ae<\/p>\n<pre>\nrake ultrasphinx:index\nrake ultrasphinx:daemon:start\n<\/pre>\n<p>\u81f3\u6b64\u53ef\u4ee5\u641c\u5c0b\u4e86:<\/p>\n<pre>\n  @search = Ultrasphinx::Search.new(:query => 'keyword')\n  @search.run\n  @search.results\n<\/pre>\n<p>\u5982\u679c\u4f60\u8981\u66f4\u9032\u4e00\u6b65\u7684\u641c\u5c0b\uff0c\u50cf\u662f\u9650\u5b9a Model \u6216 Association scoping\uff0c\u5c31\u8acb\u8a8d\u771f\u505a\u529f\u8ab2\u5538<a href=\"http:\/\/blog.evanweaver.com\/files\/doc\/fauna\/ultrasphinx\/files\/README.html\">Ultrasphinx \u6587\u4ef6<\/a>\u56c9<\/a>\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update(2009\/3\/31): \u9664\u4e86 ultrasphinx \u4e4b\u5916\uff0c\u9084\u6709\u4e00\u5957 Ruby library  &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/ihower.tw\/blog\/1716-fulltext-search-sphinx-on-rails\" class=\"more-link\">\u95b1\u8b80\u5168\u6587<span class=\"screen-reader-text\">\u3008\u5168\u6587\u641c\u5c0b Sphinx on Rails\u3009<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[53],"tags":[],"class_list":["post-1716","post","type-post","status-publish","format-standard","hentry","category-rails","entry"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1q6tG-rG","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/posts\/1716","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/comments?post=1716"}],"version-history":[{"count":8,"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/posts\/1716\/revisions"}],"predecessor-version":[{"id":8321,"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/posts\/1716\/revisions\/8321"}],"wp:attachment":[{"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/media?parent=1716"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/categories?post=1716"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ihower.tw\/blog\/wp-json\/wp\/v2\/tags?post=1716"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}