New and Announcement search. Disabled impression.
This commit is contained in:
parent
033667f99b
commit
f9bdb4a327
|
@ -5,7 +5,8 @@ log/*.log
|
|||
tmp/**/*
|
||||
public/uploads/**/*
|
||||
uploads/**/*
|
||||
|
||||
public/panel/**/*
|
||||
public/index.html
|
||||
.DS_Store
|
||||
|
||||
*.swp
|
||||
|
|
8
Gemfile
8
Gemfile
|
@ -41,9 +41,15 @@ gem 'rb-readline' if RUBY_PLATFORM.downcase.include?("linux")
|
|||
|
||||
gem "impressionist", :require => "impressionist", :path => "vendor/impressionist"
|
||||
|
||||
gem "tire"
|
||||
|
||||
|
||||
gem 'redis','>= 2.1.1'
|
||||
gem 'chinese_pinyin', '0.4.1'
|
||||
# add rmmseg if you need search by segment words
|
||||
gem 'rmmseg-cpp-huacnlee', '0.2.9'
|
||||
gem 'redis-namespace','~> 1.0.2'
|
||||
gem 'redis-search', '0.7.1'
|
||||
|
||||
# Gems used only for assets and not required
|
||||
# in production environments by default.
|
||||
group :assets do
|
||||
|
|
21
Gemfile.lock
21
Gemfile.lock
|
@ -66,6 +66,7 @@ GEM
|
|||
carrierwave-mongoid (0.1.3)
|
||||
carrierwave (>= 0.5.6)
|
||||
mongoid (~> 2.1)
|
||||
chinese_pinyin (0.4.1)
|
||||
chronic (0.6.7)
|
||||
coffee-rails (3.1.1)
|
||||
coffee-script (>= 2.2.0)
|
||||
|
@ -96,7 +97,6 @@ GEM
|
|||
railties (>= 3.0.0)
|
||||
fastercsv (1.5.4)
|
||||
haml (3.1.4)
|
||||
hashr (0.0.21)
|
||||
hike (1.2.1)
|
||||
hoe (2.16.1)
|
||||
rake (~> 0.8)
|
||||
|
@ -176,6 +176,10 @@ GEM
|
|||
redis (2.2.2)
|
||||
redis-namespace (1.0.3)
|
||||
redis (< 3.0.0)
|
||||
redis-search (0.7.1)
|
||||
chinese_pinyin (>= 0.3.0)
|
||||
redis (>= 2.1.1)
|
||||
redis-namespace (~> 1.0.2)
|
||||
resque (1.20.0)
|
||||
multi_json (~> 1.0)
|
||||
redis-namespace (~> 1.0.2)
|
||||
|
@ -187,8 +191,7 @@ GEM
|
|||
redis (>= 2.0.1)
|
||||
resque (>= 1.8.0)
|
||||
rufus-scheduler
|
||||
rest-client (1.6.7)
|
||||
mime-types (>= 1.16)
|
||||
rmmseg-cpp-huacnlee (0.2.9)
|
||||
rsolr (1.0.8)
|
||||
builder (>= 2.1.2)
|
||||
rspec (2.8.0)
|
||||
|
@ -261,12 +264,6 @@ GEM
|
|||
tilt (1.3.3)
|
||||
tinymce-rails (3.4.8)
|
||||
railties (>= 3.1)
|
||||
tire (0.4.2)
|
||||
activemodel (>= 3.0)
|
||||
hashr (~> 0.0.19)
|
||||
multi_json (~> 1.0)
|
||||
rake
|
||||
rest-client (~> 1.6)
|
||||
transaction-simple (1.4.0)
|
||||
hoe (>= 1.1.7)
|
||||
treetop (1.4.10)
|
||||
|
@ -299,6 +296,7 @@ DEPENDENCIES
|
|||
bson_ext
|
||||
carrierwave
|
||||
carrierwave-mongoid
|
||||
chinese_pinyin (= 0.4.1)
|
||||
coffee-rails
|
||||
database_cleaner
|
||||
delorean
|
||||
|
@ -322,9 +320,13 @@ DEPENDENCIES
|
|||
radius
|
||||
rails (>= 3.1.0, < 3.2.0)
|
||||
rake
|
||||
redis (>= 2.1.1)
|
||||
redis-namespace (~> 1.0.2)
|
||||
redis-search (= 0.7.1)
|
||||
resque
|
||||
resque-restriction
|
||||
resque-scheduler
|
||||
rmmseg-cpp-huacnlee (= 0.2.9)
|
||||
rspec (~> 2.0)
|
||||
rspec-rails (~> 2.0)
|
||||
ruby-debug19
|
||||
|
@ -337,6 +339,5 @@ DEPENDENCIES
|
|||
sprockets
|
||||
sunspot-rails-tester
|
||||
tinymce-rails
|
||||
tire
|
||||
uglifier
|
||||
watchr
|
||||
|
|
|
@ -19,7 +19,7 @@ class PagesController < ApplicationController
|
|||
#begin
|
||||
@item = Item.first(:conditions => {:path => params[:page_name]})
|
||||
if @item && @item.is_published && (@item.enabled_for.nil? ? true : @item.enabled_for.include?(I18n.locale.to_s))
|
||||
impressionist(@item)
|
||||
# impressionist(@item)
|
||||
case @item._type
|
||||
when 'Page'
|
||||
render_page
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
require "redis"
|
||||
require "redis-namespace"
|
||||
require "redis-search"
|
||||
# don't forget change namespace
|
||||
redis = Redis.new(:host => "127.0.0.1",:port => "6379")
|
||||
# We suggest you use a special db in Redis, when you need to clear all data, you can use flushdb command to clear them.
|
||||
redis.select(3)
|
||||
# Give a special namespace as prefix for Redis key, when your have more than one project used redis-search, this config will make them work fine.
|
||||
redis = Redis::Namespace.new("orbit_nccu:redis_search2", :redis => redis)
|
||||
Redis::Search.configure do |config|
|
||||
config.redis = redis
|
||||
config.complete_max_length = 100
|
||||
config.pinyin_match = true
|
||||
# use rmmseg, true to disable it, it can save memroy
|
||||
config.disable_rmmseg = false
|
||||
end
|
||||
Bulletin.new
|
||||
NewsBulletin.new
|
|
@ -0,0 +1,11 @@
|
|||
# encoding: UTF-8
|
||||
namespace :matt_dev do
|
||||
desc 'Testing Searching'
|
||||
task :searching_01 => :environment do
|
||||
a= Redis::Search.query("Bulletin",'我',:conditions =>{:is_checked=>true,:is_hidden=>false})
|
||||
p a
|
||||
a= Redis::Search.query("NewsBulletin",'社科院',:conditions =>{:is_checked=>true,:is_hidden=>false})
|
||||
p a
|
||||
# p Pinyin.t('台灣不是中國的一部分')
|
||||
end
|
||||
end
|
885
tmp/tire-dsl.rb
885
tmp/tire-dsl.rb
|
@ -1,885 +0,0 @@
|
|||
# encoding: UTF-8
|
||||
#
|
||||
# **Tire** provides rich and comfortable Ruby API for the
|
||||
# [_ElasticSearch_](http://www.elasticsearch.org/) search engine/database.
|
||||
#
|
||||
# _ElasticSearch_ is a scalable, distributed, cloud-ready, highly-available
|
||||
# full-text search engine and database, communicating by JSON over RESTful HTTP,
|
||||
# based on [Lucene](http://lucene.apache.org/), written in Java.
|
||||
#
|
||||
# <img src="http://github.com/favicon.ico" style="position:relative; top:2px">
|
||||
# _Tire_ is open source, and you can download or clone the source code
|
||||
# from <https://github.com/karmi/tire>.
|
||||
#
|
||||
# By following these instructions you should have the search running
|
||||
# on a sane operation system in less then 10 minutes.
|
||||
|
||||
# Note, that this file can be executed directly:
|
||||
#
|
||||
# ruby -I lib examples/tire-dsl.rb
|
||||
#
|
||||
|
||||
|
||||
#### Installation
|
||||
|
||||
# Install _Tire_ with _Rubygems_:
|
||||
|
||||
#
|
||||
# gem install tire
|
||||
#
|
||||
require 'rubygems'
|
||||
require 'colorize'
|
||||
|
||||
# _Tire_ uses the [_multi_json_](https://github.com/intridea/multi_json) gem as a generic JSON library.
|
||||
# We want to use the [_yajl-ruby_](https://github.com/brianmario/yajl-ruby) gem in its full on mode here.
|
||||
#
|
||||
require 'yajl/json_gem'
|
||||
|
||||
# Now, let's require the _Tire_ gem itself, and we're ready to go.
|
||||
#
|
||||
require 'tire'
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
# We'll need a working and running _ElasticSearch_ server, of course. Thankfully, that's easy.
|
||||
( puts <<-"INSTALL" ; exit(1) ) unless (RestClient.get('http://localhost:9200') rescue false)
|
||||
|
||||
[ERROR] You don’t appear to have ElasticSearch installed. Please install and launch it with the following commands:
|
||||
|
||||
curl -k -L -o elasticsearch-0.19.0.tar.gz http://github.com/downloads/elasticsearch/elasticsearch/elasticsearch-0.19.0.tar.gz
|
||||
tar -zxvf elasticsearch-0.19.0.tar.gz
|
||||
./elasticsearch-0.19.0/bin/elasticsearch -f
|
||||
INSTALL
|
||||
|
||||
### Storing and indexing documents
|
||||
|
||||
# Let's initialize an index named “articles”.
|
||||
#
|
||||
Tire.index 'articles' do
|
||||
# To make sure it's fresh, let's delete any existing index with the same name.
|
||||
#
|
||||
delete
|
||||
# And then, let's create it.
|
||||
#
|
||||
create
|
||||
|
||||
# We want to store and index some articles with `title`, `tags` and `published_on` properties.
|
||||
# Simple Hashes are OK. The default type is „document”.
|
||||
#
|
||||
store :title => '復興「校球」 政大男足決戰UFA足球聯賽', :tags => ['足球'], :published_on => '2011-01-01'
|
||||
store :title => '社科院舉辦碩博士班畢業生撥穗典禮', :tags => ['博士班', '畢業'], :published_on => '2011-01-02'
|
||||
|
||||
# We usually want to set a specific _type_ for the document in _ElasticSearch_.
|
||||
# Simply setting a `type` property is OK.
|
||||
#
|
||||
store :type => 'article',
|
||||
:title => '支持政大學子 羅家倫之女設立獎學金',
|
||||
:tags => ['獎學金'],
|
||||
:published_on => '2011-01-02'
|
||||
|
||||
# We may want to wrap your data in a Ruby class, and use it when storing data.
|
||||
# The contract required of such a class is very simple.
|
||||
#
|
||||
class Article
|
||||
|
||||
#
|
||||
attr_reader :title, :tags, :published_on
|
||||
def initialize(attributes={})
|
||||
@attributes = attributes
|
||||
@attributes.each_pair { |name,value| instance_variable_set :"@#{name}", value }
|
||||
end
|
||||
|
||||
# It must provide a `type`, `_type` or `document_type` method for propper mapping.
|
||||
#
|
||||
def type
|
||||
'article'
|
||||
end
|
||||
|
||||
# And it must provide a `to_indexed_json` method for conversion to JSON.
|
||||
#
|
||||
def to_indexed_json
|
||||
@attributes.to_json
|
||||
end
|
||||
end
|
||||
|
||||
# Note: Since our class takes a Hash of attributes on initialization, we may even
|
||||
# wrap the results in instances of this class; we'll see how to do that further below.
|
||||
#
|
||||
article = Article.new :title => '親身感受臺灣特色 日本田野研究團政大學習',
|
||||
:tags => ['臺灣特色', '日本'],
|
||||
:published_on => '2011-01-03'
|
||||
|
||||
# Let's store the `article`, now.
|
||||
#
|
||||
store article
|
||||
|
||||
# And let's „force refresh“ the index, so we can query it immediately.
|
||||
#
|
||||
refresh
|
||||
end
|
||||
|
||||
# We may want to define a specific [mapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index.html)
|
||||
# for the index.
|
||||
|
||||
Tire.index 'articles' do
|
||||
# To do so, let's just pass a Hash containing the specified mapping to the `Index#create` method.
|
||||
#
|
||||
create :mappings => {
|
||||
|
||||
# Let's specify for which _type_ of documents this mapping should be used:
|
||||
# „article”, in our case.
|
||||
#
|
||||
:article => {
|
||||
:properties => {
|
||||
|
||||
# Let's specify the type of the field, whether it should be analyzed, ...
|
||||
#
|
||||
:id => { :type => 'string', :index => 'not_analyzed', :include_in_all => false },
|
||||
|
||||
# ... set the boost or analyzer settings for the field, etc. The _ElasticSearch_ guide
|
||||
# has [more information](http://elasticsearch.org/guide/reference/mapping/index.html).
|
||||
# Don't forget, that proper mapping is key to efficient and effective search.
|
||||
# But don't fret about getting the mapping right the first time, you won't.
|
||||
# In most cases, the default, dynamic mapping is just fine for prototyping.
|
||||
#
|
||||
:title => { :type => 'string', :analyzer => 'cjk', :boost => 2.0 },
|
||||
:tags => { :type => 'string', :analyzer => 'keyword' },
|
||||
:content => { :type => 'string', :analyzer => 'cjk' }
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
#### Bulk Indexing
|
||||
|
||||
# Of course, we may have large amounts of data, and adding them to the index one by one really isn't the best idea.
|
||||
# We can use _ElasticSearch's_ [bulk API](http://www.elasticsearch.org/guide/reference/api/bulk.html)
|
||||
# for importing the data.
|
||||
|
||||
# So, for demonstration purposes, let's suppose we have a simple collection of hashes to store.
|
||||
#
|
||||
articles = [
|
||||
|
||||
# Notice that such objects must have an `id` property!
|
||||
#
|
||||
{ :id => '1', :type => 'article', :title => '復興「校球」 政大男足決戰UFA足球聯賽', :tags => ['足球'], :published_on => '2011-01-01' },
|
||||
|
||||
# And, of course, they should contain the `type` property for the mapping to work!
|
||||
#
|
||||
{ :id => '2', :type => 'article', :title => '社科院舉辦碩博士班畢業生撥穗典禮', :tags => ['博士班', '畢業','社科院'], :published_on => '2011-01-02' },
|
||||
{ :id => '3', :type => 'article', :title => '支持政大學子 羅家倫之女設立獎學金', :tags => ['獎學金'], :published_on => '2011-01-02' },
|
||||
{ :id => '4', :type => 'article', :title => '親身感受臺灣特色 日本田野研究團政大學習', :tags => ['臺灣特色', '日本'], :published_on => '2011-01-03' }
|
||||
]
|
||||
|
||||
# We can just push them into the index in one go.
|
||||
#
|
||||
Tire.index 'articles' do
|
||||
import articles
|
||||
end
|
||||
|
||||
# Of course, we can easily manipulate the documents before storing them in the index.
|
||||
#
|
||||
Tire.index 'articles' do
|
||||
delete
|
||||
|
||||
# ... by passing a block to the `import` method. The collection will
|
||||
# be available in the block argument.
|
||||
#
|
||||
import articles do |documents|
|
||||
|
||||
# We will capitalize every _title_ and return the manipulated collection
|
||||
# back to the `import` method.
|
||||
#
|
||||
documents.map { |document| document.update(:title => document[:title].capitalize) }
|
||||
end
|
||||
|
||||
refresh
|
||||
end
|
||||
|
||||
### Searching
|
||||
|
||||
# With the documents indexed and stored in the _ElasticSearch_ database, we can search them, finally.
|
||||
#
|
||||
# _Tire_ exposes the search interface via simple domain-specific language.
|
||||
|
||||
#### Simple Query String Searches
|
||||
|
||||
# We can do simple searches, like searching for articles containing “One” in their title.
|
||||
#
|
||||
s = Tire.search('news_bulletins') do
|
||||
query do
|
||||
string "title:政大"
|
||||
end
|
||||
end
|
||||
|
||||
# The results:
|
||||
# * One [tags: ruby]
|
||||
#
|
||||
s.results.each do |document|
|
||||
puts "Test1==============================Has results: #{s.results.count}".yellow
|
||||
puts "* #{ document.title } [tags: ]"
|
||||
end
|
||||
|
||||
# Or, we can search for articles published between January, 1st and January, 2nd.
|
||||
#
|
||||
puts "Test2==Or, we can search for articles published between January, 1st and January, 2nd.=Has results: #{s.results.count}".yellow
|
||||
s = Tire.search('articles') do
|
||||
query do
|
||||
string "published_on:[2011-01-01 TO 2011-01-02]"
|
||||
end
|
||||
end
|
||||
|
||||
# The results:
|
||||
# * One [published: 2011-01-01]
|
||||
# * Two [published: 2011-01-02]
|
||||
# * Three [published: 2011-01-02]
|
||||
#
|
||||
s.results.each do |document|
|
||||
puts "* #{ document.title } [published: #{document.published_on}]"
|
||||
end
|
||||
|
||||
# Notice, that we can access local variables from the _enclosing scope_.
|
||||
# (Of course, we may write the blocks in shorter notation.)
|
||||
|
||||
# We will define the query in a local variable named `q`...
|
||||
#
|
||||
q = "title:T*"
|
||||
# ... and we can use it inside the `query` block.
|
||||
#
|
||||
s = Tire.search('articles') { query { string q } }
|
||||
|
||||
# The results:
|
||||
# * Two [tags: ruby, python]
|
||||
# * Three [tags: java]
|
||||
#
|
||||
puts "Test3==and we can use it inside the `query` block..[ #{q} ]=Has results: #{s.results.count}".yellow
|
||||
s.results.each do |document|
|
||||
puts "* #{ document.title } [tags:]"
|
||||
end
|
||||
|
||||
# Often, we need to access variables or methods defined in the _outer scope_.
|
||||
# To do that, we have to use a slight variation of the DSL.
|
||||
#
|
||||
|
||||
# Let's assume we have a plain Ruby class, named `Article`.
|
||||
#
|
||||
class Article
|
||||
|
||||
# We will define the query in a class method...
|
||||
#
|
||||
def self.q
|
||||
"title:T*"
|
||||
end
|
||||
|
||||
# ... and wrap the _Tire_ search method in another one.
|
||||
def self.search
|
||||
|
||||
# Notice how we pass the `search` object around as a block argument.
|
||||
#
|
||||
Tire.search('articles') do |search|
|
||||
|
||||
# And we pass the query object in a similar matter.
|
||||
#
|
||||
search.query do |query|
|
||||
|
||||
# Which means we can access the `q` class method.
|
||||
#
|
||||
query.string self.q
|
||||
end
|
||||
end.results
|
||||
end
|
||||
end
|
||||
|
||||
# We may use any valid [Lucene query syntax](http://lucene.apache.org/java/3_0_3/queryparsersyntax.html)
|
||||
# for the `query_string` queries.
|
||||
|
||||
# For debugging our queries, we can display the JSON which is being sent to _ElasticSearch_.
|
||||
#
|
||||
# {"query":{"query_string":{"query":"title:T*"}}}
|
||||
#
|
||||
puts "", "Query:", "-"*80
|
||||
puts s.to_json.green
|
||||
|
||||
# Or better yet, we may display a complete `curl` command to recreate the request in terminal,
|
||||
# so we can see the naked response, tweak request parameters and meditate on problems.
|
||||
#
|
||||
# curl -X POST "http://localhost:9200/articles/_search?pretty=true" \
|
||||
# -d '{"query":{"query_string":{"query":"title:T*"}}}'
|
||||
#
|
||||
puts "", "Try the query in Curl:", "-"*80
|
||||
puts s.to_curl.green
|
||||
|
||||
|
||||
### Logging
|
||||
|
||||
# For debugging more complex situations, we can enable logging, so requests and responses
|
||||
# will be logged using this `curl`-friendly format.
|
||||
|
||||
Tire.configure do
|
||||
|
||||
# By default, at the _info_ level, only the `curl`-format of request and
|
||||
# basic information about the response will be logged:
|
||||
#
|
||||
# # 2011-04-24 11:34:01:150 [CREATE] ("articles")
|
||||
# #
|
||||
# curl -X POST "http://localhost:9200/articles"
|
||||
#
|
||||
# # 2011-04-24 11:34:01:152 [200]
|
||||
#
|
||||
logger 'elasticsearch.log'
|
||||
|
||||
# For debugging, we can switch to the _debug_ level, which will log the complete JSON responses.
|
||||
#
|
||||
# That's very convenient if we want to post a recreation of some problem or solution
|
||||
# to the mailing list, IRC channel, etc.
|
||||
#
|
||||
logger 'elasticsearch.log', :level => 'debug'
|
||||
|
||||
# Note that we can pass any [`IO`](http://www.ruby-doc.org/core/classes/IO.html)-compatible Ruby object as a logging device.
|
||||
#
|
||||
logger STDERR
|
||||
end
|
||||
|
||||
### Configuration
|
||||
|
||||
# As we have just seen with logging, we can configure various parts of _Tire_.
|
||||
#
|
||||
Tire.configure do
|
||||
|
||||
# First of all, we can configure the URL for _ElasticSearch_.
|
||||
#
|
||||
url "http://search.example.com"
|
||||
|
||||
# Second, we may want to wrap the result items in our own class, for instance
|
||||
# the `Article` class set above.
|
||||
#
|
||||
wrapper Article
|
||||
|
||||
# Finally, we can reset one or all configuration settings to their defaults.
|
||||
#
|
||||
reset :url
|
||||
reset
|
||||
|
||||
end
|
||||
|
||||
|
||||
### Complex Searching
|
||||
|
||||
# Query strings are convenient for simple searches, but we may want to define our queries more expressively,
|
||||
# using the _ElasticSearch_ [Query DSL](http://www.elasticsearch.org/guide/reference/query-dsl/index.html).
|
||||
#
|
||||
s = Tire.search('articles') do
|
||||
|
||||
# Let's suppose we want to search for articles with specific _tags_, in our case “ruby” _or_ “python”.
|
||||
#
|
||||
query do
|
||||
|
||||
# That's a great excuse to use a [_terms_](http://elasticsearch.org/guide/reference/query-dsl/terms-query.html)
|
||||
# query.
|
||||
#
|
||||
terms :tags, ['ruby', 'python']
|
||||
end
|
||||
end
|
||||
|
||||
# The search, as expected, returns three articles, all tagged “ruby” — among other tags:
|
||||
#
|
||||
# * Two [tags: ruby, python]
|
||||
# * One [tags: ruby]
|
||||
# * Four [tags: ruby, php]
|
||||
#
|
||||
puts "Test4==The search, as expected, returns three articles, all tagged “STHs” — among other tags.Has results: #{s.results.count}".yellow
|
||||
s.results.each do |document|
|
||||
puts "* #{ document.title } [tags: ]"
|
||||
end
|
||||
|
||||
# What if we wanted to search for articles tagged both “ruby” _and_ “python”?
|
||||
#
|
||||
s = Tire.search('articles') do
|
||||
query do
|
||||
|
||||
# That's a great excuse to specify `minimum_match` for the query.
|
||||
#
|
||||
terms :tags, ['ruby', 'python'], :minimum_match => 2
|
||||
end
|
||||
end
|
||||
|
||||
# The search, as expected, returns one article, tagged with _both_ “ruby” and “python”:
|
||||
#
|
||||
# * Two [tags: ruby, python]
|
||||
#
|
||||
puts "Test5==The search, as expected, returns one article, tagged with _both_ 'ruby' and 'python'.Has results: #{s.results.count}".yellow
|
||||
s.results.each do |document|
|
||||
puts "* #{ document.title } [tags: ]"
|
||||
end
|
||||
|
||||
#### Boolean Queries
|
||||
|
||||
# Quite often, we need complex queries with boolean logic.
|
||||
# Instead of composing long query strings such as `tags:ruby OR tags:java AND NOT tags:python`,
|
||||
# we can use the [_bool_](http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html)
|
||||
# query.
|
||||
|
||||
s = Tire.search('news_bulletins') do
|
||||
query do
|
||||
|
||||
# In _Tire_, we can build `bool` queries declaratively, as usual.
|
||||
boolean do
|
||||
|
||||
# Let's define a `should` (`OR`) query for _ruby_,
|
||||
#
|
||||
should { string 'title:政大' }
|
||||
|
||||
# as well as for _java_,
|
||||
must_not { string 'title:復興' }
|
||||
|
||||
# while defining a `must_not` (`AND NOT`) query for _python_.
|
||||
# must_not { string 'tags:python' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# The search returns these documents:
|
||||
#
|
||||
# * One [tags: ruby]
|
||||
# * Three [tags: java]
|
||||
# * Four [tags: ruby, php]
|
||||
puts "Test6==Boolean Queries.Has results: #{s.results.count}".yellow
|
||||
s.results.each do |document|
|
||||
puts "* #{ document.title } [tags: ]"
|
||||
end
|
||||
|
||||
puts "Test7== mix and reuse Boolean Queries: #{s.results.count}".yellow
|
||||
# The best thing about `boolean` queries is that we can very easily save these partial queries as Ruby blocks,
|
||||
# to mix and reuse them later, since we can call the `boolean` method multiple times.
|
||||
#
|
||||
|
||||
# Let's define the query for the _tags_ property,
|
||||
#
|
||||
tags_query = lambda do |boolean|
|
||||
boolean.should { string 'tags:ruby' }
|
||||
boolean.should { string 'tags:java' }
|
||||
end
|
||||
|
||||
# ... and a query for the _published_on_ property.
|
||||
published_on_query = lambda do |boolean|
|
||||
boolean.must { string 'published_on:[2011-01-01 TO 2011-01-02]' }
|
||||
end
|
||||
|
||||
# Now, we can use the `tags_query` on its own.
|
||||
#
|
||||
Tire.search('articles') { query { boolean &tags_query } }
|
||||
|
||||
# Or, we can combine it with the `published_on` query.
|
||||
#
|
||||
Tire.search('articles') do
|
||||
query do
|
||||
boolean &tags_query
|
||||
boolean &published_on_query
|
||||
end
|
||||
end
|
||||
|
||||
# _ElasticSearch_ supports many types of [queries](http://www.elasticsearch.org/guide/reference/query-dsl/).
|
||||
#
|
||||
# Eventually, _Tire_ will support all of them. So far, only these are supported:
|
||||
#
|
||||
# * [string](http://www.elasticsearch.org/guide/reference/query-dsl/query-string-query.html)
|
||||
# * [text](http://www.elasticsearch.org/guide/reference/query-dsl/text-query.html)
|
||||
# * [term](http://elasticsearch.org/guide/reference/query-dsl/term-query.html)
|
||||
# * [terms](http://elasticsearch.org/guide/reference/query-dsl/terms-query.html)
|
||||
# * [bool](http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html)
|
||||
# * [custom_score](http://www.elasticsearch.org/guide/reference/query-dsl/custom-score-query.html)
|
||||
# * [fuzzy](http://www.elasticsearch.org/guide/reference/query-dsl/fuzzy-query.html)
|
||||
# * [all](http://www.elasticsearch.org/guide/reference/query-dsl/match-all-query.html)
|
||||
# * [ids](http://www.elasticsearch.org/guide/reference/query-dsl/ids-query.html)
|
||||
|
||||
puts "Topic#### Faceted Search ==> SKIP".yellow
|
||||
|
||||
|
||||
|
||||
# # _ElasticSearch_ makes it trivial to retrieve complex aggregated data from our index/database,
|
||||
# # so called [_facets_](http://www.elasticsearch.org/guide/reference/api/search/facets/index.html).
|
||||
|
||||
# # Let's say we want to display article counts for every tag in the database.
|
||||
# # For that, we'll use a _terms_ facet.
|
||||
|
||||
# #
|
||||
# s = Tire.search 'articles' do
|
||||
|
||||
# # We will search for articles whose title begins with letter “T”,
|
||||
# #
|
||||
# query { string 'title:T*' }
|
||||
|
||||
# # and retrieve the counts “bucketed” by `tags`.
|
||||
# #
|
||||
# facet 'tags' do
|
||||
# terms :tags
|
||||
# end
|
||||
# end
|
||||
|
||||
# # As we see, our query has found two articles, and if you recall our articles from above,
|
||||
# # _Two_ is tagged with “ruby” and “python”, while _Three_ is tagged with “java”.
|
||||
# #
|
||||
# # Found 2 articles: Three, Two
|
||||
# #
|
||||
# # The counts shouldn't surprise us:
|
||||
# #
|
||||
# # Counts by tag:
|
||||
# # -------------------------
|
||||
# # ruby 1
|
||||
# # python 1
|
||||
# # java 1
|
||||
# #
|
||||
# puts "Found #{s.results.count} articles: #{s.results.map(&:title).join(', ')}"
|
||||
# puts "Counts by tag:", "-"*25
|
||||
# s.results.facets['tags']['terms'].each do |f|
|
||||
# puts "#{f['term'].ljust(10)} #{f['count']}"
|
||||
# end
|
||||
|
||||
# # These counts are based on the scope of our current query.
|
||||
# # What if we wanted to display aggregated counts by `tags` across the whole database?
|
||||
|
||||
# #
|
||||
# s = Tire.search 'articles' do
|
||||
|
||||
# # Let's repeat the search for “T”...
|
||||
# #
|
||||
# query { string 'title:T*' }
|
||||
|
||||
# facet 'global-tags', :global => true do
|
||||
|
||||
# # ...but set the `global` scope for the facet in this case.
|
||||
# #
|
||||
# terms :tags
|
||||
# end
|
||||
|
||||
# # We can even _combine_ facets scoped to the current query
|
||||
# # with globally scoped facets — we'll just use a different name.
|
||||
# #
|
||||
# facet 'current-tags' do
|
||||
# terms :tags
|
||||
# end
|
||||
# end
|
||||
|
||||
# # Aggregated results for the current query are the same as previously:
|
||||
# #
|
||||
# # Current query facets:
|
||||
# # -------------------------
|
||||
# # ruby 1
|
||||
# # python 1
|
||||
# # java 1
|
||||
# #
|
||||
# puts "Current query facets:", "-"*25
|
||||
# s.results.facets['current-tags']['terms'].each do |f|
|
||||
# puts "#{f['term'].ljust(10)} #{f['count']}"
|
||||
# end
|
||||
|
||||
# # On the other hand, aggregated results for the global scope include also
|
||||
# # tags for articles not matched by the query, such as “java” or “php”:
|
||||
# #
|
||||
# # Global facets:
|
||||
# # -------------------------
|
||||
# # ruby 3
|
||||
# # python 1
|
||||
# # php 1
|
||||
# # java 1
|
||||
# #
|
||||
# puts "Global facets:", "-"*25
|
||||
# s.results.facets['global-tags']['terms'].each do |f|
|
||||
# puts "#{f['term'].ljust(10)} #{f['count']}"
|
||||
# end
|
||||
|
||||
# # _ElasticSearch_ supports many advanced types of facets, such as those for computing statistics or geographical distance.
|
||||
# #
|
||||
# # Eventually, _Tire_ will support all of them. So far, only these are supported:
|
||||
# #
|
||||
# # * [terms](http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html)
|
||||
# # * [date](http://www.elasticsearch.org/guide/reference/api/search/facets/date-histogram-facet.html)
|
||||
# # * [range](http://www.elasticsearch.org/guide/reference/api/search/facets/range-facet.html)
|
||||
# # * [histogram](http://www.elasticsearch.org/guide/reference/api/search/facets/histogram-facet.html)
|
||||
# # * [statistical](http://www.elasticsearch.org/guide/reference/api/search/facets/statistical-facet.html)
|
||||
# # * [terms_stats](http://www.elasticsearch.org/guide/reference/api/search/facets/terms-stats-facet.html)
|
||||
# # * [query](http://www.elasticsearch.org/guide/reference/api/search/facets/query-facet.html)
|
||||
|
||||
# # We have seen that _ElasticSearch_ facets enable us to fetch complex aggregations from our data.
|
||||
# #
|
||||
# # They are frequently used for another feature, „faceted navigation“.
|
||||
# # We can be combine query and facets with
|
||||
# # [filters](http://elasticsearch.org/guide/reference/api/search/filter.html),
|
||||
# # so the returned documents are restricted by certain criteria — for example to a specific category —,
|
||||
# # but the aggregation calculations are still based on the original query.
|
||||
|
||||
|
||||
# #### Filtered Search
|
||||
|
||||
# # So, let's make our search a bit more complex. Let's search for articles whose titles begin
|
||||
# # with letter “T”, again, but filter the results, so only the articles tagged “ruby”
|
||||
# # are returned.
|
||||
# #
|
||||
# s = Tire.search 'articles' do
|
||||
|
||||
# # We will use just the same **query** as before.
|
||||
# #
|
||||
# query { string 'title:T*' }
|
||||
|
||||
# # But we will add a _terms_ **filter** based on tags.
|
||||
# #
|
||||
# filter :terms, :tags => ['ruby']
|
||||
|
||||
# # And, of course, our facet definition.
|
||||
# #
|
||||
# facet('tags') { terms :tags }
|
||||
|
||||
# end
|
||||
|
||||
# # We see that only the article _Two_ (tagged “ruby” and “python”) is returned,
|
||||
# # _not_ the article _Three_ (tagged “java”):
|
||||
# #
|
||||
# # * Two [tags: ruby, python]
|
||||
# #
|
||||
# s.results.each do |document|
|
||||
# puts "* #{ document.title } [tags: ]"
|
||||
# end
|
||||
|
||||
# # The _count_ for article _Three_'s tags, “java”, on the other hand, _is_ in fact included:
|
||||
# #
|
||||
# # Counts by tag:
|
||||
# # -------------------------
|
||||
# # ruby 1
|
||||
# # python 1
|
||||
# # java 1
|
||||
# #
|
||||
# puts "Counts by tag:", "-"*25
|
||||
# s.results.facets['tags']['terms'].each do |f|
|
||||
# puts "#{f['term'].ljust(10)} #{f['count']}"
|
||||
# end
|
||||
|
||||
# #### Sorting
|
||||
|
||||
# # By default, the results are sorted according to their relevancy.
|
||||
# #
|
||||
# s = Tire.search('articles') { query { string 'tags:ruby' } }
|
||||
|
||||
# s.results.each do |document|
|
||||
# puts "* #{ document.title } " +
|
||||
# "[tags: ; " +
|
||||
|
||||
# # The score is available as the `_score` property.
|
||||
# #
|
||||
# "score: #{document._score}]"
|
||||
# end
|
||||
|
||||
# # The results:
|
||||
# #
|
||||
# # * One [tags: ruby; score: 0.30685282]
|
||||
# # * Four [tags: ruby, php; score: 0.19178301]
|
||||
# # * Two [tags: ruby, python; score: 0.19178301]
|
||||
|
||||
# # But, what if we want to sort the results based on some other criteria,
|
||||
# # such as published date or product price? We can do that.
|
||||
# #
|
||||
# s = Tire.search 'articles' do
|
||||
|
||||
# # We will search for articles tagged “ruby”, again, ...
|
||||
# #
|
||||
# query { string 'tags:ruby' }
|
||||
|
||||
# # ... but will sort them by their `title`, in descending order.
|
||||
# #
|
||||
# sort { by :title, 'desc' }
|
||||
# end
|
||||
|
||||
# # The results:
|
||||
# #
|
||||
# # * Two
|
||||
# # * One
|
||||
# # * Four
|
||||
# #
|
||||
# s.results.each do |document|
|
||||
# puts "* #{ document.title }"
|
||||
# end
|
||||
|
||||
# # Of course, it's possible to combine more fields in the sorting definition.
|
||||
|
||||
# s = Tire.search 'articles' do
|
||||
|
||||
# # We will just get all articles in this case.
|
||||
# #
|
||||
# query { all }
|
||||
|
||||
# sort do
|
||||
|
||||
# # We will sort the results by their `published_on` property in _ascending_ order (the default),
|
||||
# #
|
||||
# by :published_on
|
||||
|
||||
# # and by their `title` property, in _descending_ order.
|
||||
# #
|
||||
# by :title, 'desc'
|
||||
# end
|
||||
# end
|
||||
|
||||
# # The results:
|
||||
# # * One (Published on: 2011-01-01)
|
||||
# # * Two (Published on: 2011-01-02)
|
||||
# # * Three (Published on: 2011-01-02)
|
||||
# # * Four (Published on: 2011-01-03)
|
||||
# #
|
||||
# s.results.each do |document|
|
||||
# puts "* #{ document.title.ljust(10) } (Published on: #{ document.published_on })"
|
||||
# end
|
||||
|
||||
# #### Highlighting
|
||||
|
||||
# # Often, we want to highlight the snippets matching our query in the displayed results.
|
||||
# # _ElasticSearch_ provides rich
|
||||
# # [highlighting](http://www.elasticsearch.org/guide/reference/api/search/highlighting.html)
|
||||
# # features, and _Tire_ makes them trivial to use.
|
||||
# #
|
||||
# s = Tire.search 'articles' do
|
||||
|
||||
# # Let's search for documents containing word “Two” in their titles,
|
||||
# query { string 'title:Two' }
|
||||
|
||||
# # and instruct _ElasticSearch_ to highlight relevant snippets.
|
||||
# #
|
||||
# highlight :title
|
||||
# end
|
||||
|
||||
# # The results:
|
||||
# # Title: Two; Highlighted: <em>Two</em>
|
||||
# #
|
||||
# s.results.each do |document|
|
||||
# puts "Title: #{ document.title }; Highlighted: #{document.highlight.title}"
|
||||
# end
|
||||
|
||||
# # We can configure many options for highlighting, such as:
|
||||
# #
|
||||
# s = Tire.search 'articles' do
|
||||
# query { string 'title:Two' }
|
||||
|
||||
# # • specify the fields to highlight
|
||||
# #
|
||||
# highlight :title, :body
|
||||
|
||||
# # • specify their individual options
|
||||
# #
|
||||
# highlight :title, :body => { :number_of_fragments => 0 }
|
||||
|
||||
# # • or specify global highlighting options, such as the wrapper tag
|
||||
# #
|
||||
# highlight :title, :body, :options => { :tag => '<strong class="highlight">' }
|
||||
# end
|
||||
|
||||
# #### Percolation
|
||||
|
||||
# # _ElasticSearch_ comes with one very interesting, and rather unique feature:
|
||||
# # [_percolation_](http://www.elasticsearch.org/guide/reference/api/percolate.html).
|
||||
|
||||
# # It works in a „reverse search“ manner to regular search workflow of adding
|
||||
# # documents to the index and then querying them.
|
||||
# # Percolation allows us to register a query, and ask if a specific document
|
||||
# # matches it, either on demand, or immediately as the document is being indexed.
|
||||
|
||||
# # Let's review an example for an index named _weather_.
|
||||
# # We will register three queries for percolation against this index.
|
||||
# #
|
||||
# index = Tire.index('weather') do
|
||||
# delete
|
||||
# create
|
||||
|
||||
# # First, a query named _warning_,
|
||||
# #
|
||||
# register_percolator_query('warning', :tags => ['warning']) { string 'warning OR severe OR extreme' }
|
||||
|
||||
# # a query named _tsunami_,
|
||||
# #
|
||||
# register_percolator_query('tsunami', :tags => ['tsunami']) { string 'tsunami' }
|
||||
|
||||
# # and a query named _floods_.
|
||||
# #
|
||||
# register_percolator_query('floods', :tags => ['floods']) { string 'flood*' }
|
||||
|
||||
# end
|
||||
|
||||
# # Notice, that we have added a _tags_ field to the query document, because it behaves
|
||||
# # just like any other document in _ElasticSearch_.
|
||||
|
||||
# # We will refresh the `_percolator` index for immediate access.
|
||||
# #
|
||||
# Tire.index('_percolator').refresh
|
||||
|
||||
# # Now, let's _percolate_ a document containing some trigger words against all registered queries.
|
||||
# #
|
||||
# matches = index.percolate(:message => '[Warning] Extreme flooding expected after tsunami wave.')
|
||||
|
||||
# # The result will contain, unsurprisingly, names of all the three registered queries:
|
||||
# #
|
||||
# # Matching queries: ["floods", "tsunami", "warning"]
|
||||
# #
|
||||
# puts "Matching queries: " + matches.inspect
|
||||
|
||||
# # We can filter the executed queries with a regular _ElasticSearch_ query passed as a block to
|
||||
# # the `percolate` method.
|
||||
# #
|
||||
# matches = index.percolate(:message => '[Warning] Extreme flooding expected after tsunami wave.') do
|
||||
# # Let's use a _terms_ query against the `tags` field.
|
||||
# term :tags, 'tsunami'
|
||||
# end
|
||||
|
||||
# # In this case, the result will contain only the name of the “tsunami” query.
|
||||
# #
|
||||
# # Matching queries: ["tsunami"]
|
||||
# #
|
||||
# puts "Matching queries: " + matches.inspect
|
||||
|
||||
# # What if we percolate another document, without the “tsunami” trigger word?
|
||||
# #
|
||||
# matches = index.percolate(:message => '[Warning] Extreme temperatures expected.') { term :tags, 'tsunami' }
|
||||
|
||||
# # As expected, we will get an empty array:
|
||||
# #
|
||||
# # Matching queries: []
|
||||
# #
|
||||
# puts "Matching queries: " + matches.inspect
|
||||
|
||||
# # Well, that's of course immensely useful for real-time search systems. But, there's more.
|
||||
# # We can _percolate_ a document _at the same time_ it is being stored in the index,
|
||||
# # getting back a list of matching queries.
|
||||
|
||||
# # Let's store a document with some trigger words in the index, and mark it for percolation.
|
||||
# #
|
||||
# response = index.store :message => '[Warning] Severe floods expected after tsunami wave.', :percolate => true
|
||||
|
||||
# # We will get the names of all matching queries in response.
|
||||
# #
|
||||
# # Matching queries: ["floods", "tsunami", "warning"]
|
||||
# #
|
||||
# puts "Matching queries: " + response['matches'].inspect
|
||||
|
||||
# # As with the _percolate_ example, we can filter the executed queries.
|
||||
# #
|
||||
# response = index.store :message => '[Warning] Severe floods expected after tsunami wave.',
|
||||
# # Let's use a simple string query for the “tsunami” tag.
|
||||
# :percolate => 'tags:tsunami'
|
||||
|
||||
# # Unsurprisingly, the response will contain just the name of the “tsunami” query.
|
||||
# #
|
||||
# # Matching queries: ["tsunami"]
|
||||
# #
|
||||
# puts "Matching queries: " + response['matches'].inspect
|
||||
|
||||
# ### ActiveModel Integration
|
||||
|
||||
# # As you can see, [_Tire_](https://github.com/karmi/tire) supports the
|
||||
# # main features of _ElasticSearch_ in Ruby.
|
||||
# #
|
||||
# # It allows you to create and delete indices, add documents, search them, retrieve the facets, highlight the results,
|
||||
# # and comes with a usable logging facility.
|
||||
# #
|
||||
# # Of course, the holy grail of any search library is easy, painless integration with your Ruby classes, and,
|
||||
# # most importantly, with ActiveRecord/ActiveModel classes.
|
||||
# #
|
||||
# # Please, check out the [README](https://github.com/karmi/tire/tree/master#readme) file for instructions
|
||||
# # how to include _Tire_-based search in your models..
|
||||
# #
|
||||
# # Send any feedback via Github issues, or ask questions in the [#elasticsearch](irc://irc.freenode.net/#elasticsearch) IRC channel.
|
|
@ -9,17 +9,24 @@ class Panel::Announcement::FrontEnd::BulletinsController < OrbitWidgetController
|
|||
# GET /bulletins.xml
|
||||
|
||||
def index
|
||||
|
||||
date_now = Time.now
|
||||
if !params[:category_id].blank?
|
||||
@bulletins = Bulletin.all.can_display.where(:bulletin_category_id => params[:category_id]).any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
|
||||
@current_category = BulletinCategory.from_id(params[:category_id]) rescue nil
|
||||
elsif !params[:tag_id].blank?
|
||||
@tag = AnnouncementTag.find(params[:tag_id]) rescue nil
|
||||
@tag = AnnouncementTag.where(key: params[:tag_id])[0] unless @tag
|
||||
@bulletins = @tag.bulletins.can_display.any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
|
||||
if !params[:search_query].blank?
|
||||
search_cond = {:is_checked=>true,:is_hidden=>false}
|
||||
search_cond.merge!({:bulletin_category_id => "#{params[:category_id]}" }) if !params[:category_id].blank?
|
||||
search = Redis::Search.query("Bulletin", params[:search_query], :conditions =>search_cond)
|
||||
search_result = search.collect{|t| t["id"]}
|
||||
@news_bulletins = Bulletin.all.can_display.any_in(_id:search_result).page( params[:page_main]).per(10)
|
||||
else
|
||||
@bulletins = Bulletin.all.can_display.any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
|
||||
date_now = Time.now
|
||||
if !params[:category_id].blank?
|
||||
@bulletins = Bulletin.all.can_display.where(:bulletin_category_id => params[:category_id]).any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
|
||||
@current_category = BulletinCategory.from_id(params[:category_id]) rescue nil
|
||||
elsif !params[:tag_id].blank?
|
||||
@tag = AnnouncementTag.find(params[:tag_id]) rescue nil
|
||||
@tag = AnnouncementTag.where(key: params[:tag_id])[0] unless @tag
|
||||
@bulletins = @tag.bulletins.can_display.any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
|
||||
else
|
||||
@bulletins = Bulletin.all.can_display.any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -47,6 +47,9 @@ class Panel::Announcement::Widget::BulletinsController < OrbitWidgetController
|
|||
get_categorys
|
||||
end
|
||||
|
||||
def bulletins_search_block
|
||||
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# encoding: utf-8
|
||||
|
||||
# require "impressionist"
|
||||
class Bulletin
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
include Mongoid::MultiParameterAttributes
|
||||
include Redis::Search
|
||||
include Impressionist::Impressionable
|
||||
|
||||
BelongsToCategory = :bulletin_category
|
||||
|
@ -13,7 +14,7 @@ class Bulletin
|
|||
|
||||
scope :searchable,where(:is_checked=>true,:is_hidden=>false,:is_pending=>false)
|
||||
|
||||
is_impressionable :counter_cache => { :column_name => :view_count }
|
||||
# is_impressionable :counter_cache => { :column_name => :view_count }
|
||||
|
||||
has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
|
||||
has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
|
||||
|
@ -62,7 +63,29 @@ class Bulletin
|
|||
after_save :save_bulletin_links
|
||||
after_save :save_bulletin_files
|
||||
|
||||
redis_search_index(:title_field => :s_title,
|
||||
:alias_field =>:s_title_en ,
|
||||
:score_field => :view_count,
|
||||
:condition_fields => [:is_checked,:is_hidden,:bulletin_category_id],
|
||||
:ext_fields => [])
|
||||
# def gen_title_for_search
|
||||
# # [s_title,s_title_en,s_text_en,s_text_zh_tw].join(' ')
|
||||
# end
|
||||
|
||||
def s_title
|
||||
self.title.zh_tw
|
||||
end
|
||||
|
||||
def s_title_en
|
||||
self.title.en
|
||||
end
|
||||
|
||||
# def s_text_en
|
||||
# Nokogiri::HTML(self.text.en).text
|
||||
# end
|
||||
# def s_text_zh_tw
|
||||
# Nokogiri::HTML(self.text.zh_tw).text
|
||||
# end
|
||||
|
||||
# scope :currently_available, lambda { |category, limit|
|
||||
# # limit ||= 5
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<%= form_tag panel_announcement_front_end_bulletins_path, method: :get do %>
|
||||
<p>
|
||||
<%= text_field_tag :search_query, params[:search_query] %>
|
||||
<%= submit_tag "Search", name: nil %>
|
||||
</p>
|
||||
<% end %>
|
|
@ -44,6 +44,7 @@ Rails.application.routes.draw do
|
|||
match "reload_bulletins" => "bulletins#reload_bulletins"
|
||||
match "reload_web_links" => "bulletins#reload_web_links"
|
||||
match "bulletins_side_bar" => "bulletins#bulletins_side_bar"
|
||||
match "bulletins_search_block" => "bulletins#bulletins_search_block"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,21 +10,10 @@ class Panel::News::FrontEnd::NewsBulletinsController < OrbitWidgetController
|
|||
|
||||
def index
|
||||
if !params[:search_query].blank?
|
||||
search_query =params[:search_query].gsub(/"/,"").split(" ")
|
||||
|
||||
words_query = lambda do |boolean|
|
||||
search_query.each do |word|
|
||||
boolean.should { string "title:#{word}" }
|
||||
#boolean.should { string "sub_title:#{word}" }
|
||||
#boolean.should { string "text:#{word}" }
|
||||
end
|
||||
end
|
||||
|
||||
search_result=Tire.search('news_bulletins') do
|
||||
query {boolean &words_query }
|
||||
#raise to_curl
|
||||
end.results.collect{|t| t.id}
|
||||
|
||||
search_cond = {:is_checked=>true,:is_hidden=>false}
|
||||
search_cond.merge!({:news_bulletin_category_id => "#{params[:category_id]}" }) if !params[:category_id].blank?
|
||||
search = Redis::Search.query("NewsBulletin", params[:search_query], :conditions =>search_cond)
|
||||
search_result = search.collect{|t| t["id"]}
|
||||
@news_bulletins = NewsBulletin.all.can_display.any_in(_id:search_result).page( params[:page_main]).per(10)
|
||||
else
|
||||
date_now = Time.now
|
||||
|
@ -50,7 +39,7 @@ class Panel::News::FrontEnd::NewsBulletinsController < OrbitWidgetController
|
|||
else
|
||||
@news_bulletin = NewsBulletin.all.can_display.where(_id: params[:id]).first
|
||||
unless @news_bulletin.disable?
|
||||
impressionist(@news_bulletin)
|
||||
# impressionist(@news_bulletin)
|
||||
get_categorys
|
||||
else
|
||||
render :nothing => true, :status => 403
|
||||
|
|
|
@ -47,8 +47,9 @@ caches_page :home_banner
|
|||
get_categorys
|
||||
end
|
||||
|
||||
# def news_bulletins_search_block
|
||||
# end
|
||||
def news_bulletins_search_block
|
||||
|
||||
end
|
||||
|
||||
def home_banner
|
||||
if !params[:category_id].blank?
|
||||
|
|
|
@ -4,6 +4,7 @@ class NewsBulletin
|
|||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
include Mongoid::MultiParameterAttributes
|
||||
include Redis::Search
|
||||
include Impressionist::Impressionable
|
||||
|
||||
BelongsToCategory = :news_bulletin_category
|
||||
|
@ -16,7 +17,7 @@ class NewsBulletin
|
|||
|
||||
scope :searchable,where(:is_checked=>true,:is_hidden=>false,:is_pending=>false)
|
||||
|
||||
is_impressionable :counter_cache => { :column_name => :view_count }
|
||||
# is_impressionable :counter_cache => { :column_name => :view_count }
|
||||
|
||||
has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
|
||||
has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
|
||||
|
@ -89,32 +90,29 @@ class NewsBulletin
|
|||
"news_bulletin"
|
||||
end
|
||||
|
||||
def to_indexed_json
|
||||
titles = title.zh_tw #+ title.en
|
||||
sub_titles = subtitle.zh_tw #+ subtitle.en
|
||||
texts = text.zh_tw #+ text.en
|
||||
{
|
||||
:_id => _id,
|
||||
:title => Nokogiri::HTML(titles).text,
|
||||
:sub_title => Nokogiri::HTML(sub_titles).text,
|
||||
:text => Nokogiri::HTML(texts).text
|
||||
}.to_json
|
||||
end
|
||||
redis_search_index(:title_field => :s_title,
|
||||
:alias_field => :s_title_en,
|
||||
:score_field => :view_count,
|
||||
:condition_fields => [:is_checked,:is_hidden,:news_bulletin_category_id],
|
||||
:ext_fields =>[])
|
||||
# def gen_title_for_search
|
||||
# # [s_title,s_title_en,s_text_en,s_text_zh_tw].join(' ')
|
||||
# end
|
||||
|
||||
def self.search( search = nil, category_id = nil )
|
||||
if category_id.to_s.size > 0 and search.to_s.size > 0
|
||||
key = /#{search}/
|
||||
find(:all, :conditions => {title: key, news_bulletin_category_id: category_id}).desc( :is_top, :postdate )
|
||||
elsif category_id.to_s.size > 0 and search.to_s.size < 1
|
||||
find(:all, :conditions => {news_bulletin_category_id: category_id}).desc( :is_top, :postdate )
|
||||
elsif search.to_s.size > 0 and category_id.to_s.size < 1
|
||||
key = /#{search}/
|
||||
find(:all, :conditions => {title: key}).desc( :is_top, :postdate )
|
||||
else
|
||||
find(:all).desc( :is_top, :postdate)
|
||||
end
|
||||
end
|
||||
def s_title
|
||||
#self.title.zh_tw
|
||||
end
|
||||
|
||||
def s_title_en
|
||||
#self.title.en
|
||||
end
|
||||
|
||||
# def s_text_en
|
||||
# Nokogiri::HTML(self.text.en).text
|
||||
# end
|
||||
# def s_text_zh_tw
|
||||
# Nokogiri::HTML(self.text.zh_tw).text
|
||||
# end
|
||||
|
||||
def self.widget_datas( category_id = nil )
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<%= form_tag panel_news_front_end_news_bulletins_path, method: :get do %>
|
||||
<p>
|
||||
<%= text_field_tag :search_query, params[:search_query] %>
|
||||
<%= hidden_field_tag :category_id, params[:category_id] %>
|
||||
<%= submit_tag "Search", name: nil %>
|
||||
</p>
|
||||
<% end %>
|
|
@ -7,7 +7,7 @@ platforms :jruby do
|
|||
end
|
||||
|
||||
platforms :ruby, :mswin, :mingw do
|
||||
# gem 'sqlite3'
|
||||
gem 'sqlite3'
|
||||
end
|
||||
|
||||
gemspec
|
||||
|
|
|
@ -29,22 +29,17 @@ module Impressionist
|
|||
end
|
||||
|
||||
def impressionist_count(options={})
|
||||
# options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now)
|
||||
# imps = options[:start_date].blank? ? impressions : impressions.where("created_at>=? and created_at<=?",options[:start_date],options[:end_date])
|
||||
# options[:filter] == :all ? imps.count : imps.count(options[:filter], :distinct => true)
|
||||
options.reverse_merge!(:filter => :request_hash, :start_date => nil, :end_date => Time.now)
|
||||
imps = options[:start_date].blank? ? impressions : impressions.where(:created_at.gte => options[:start_date], :created_at.lte => options[:end_date])
|
||||
options[:filter] == :all ? imps.count : imps.distinct(options[:filter]).count
|
||||
options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now)
|
||||
imps = options[:start_date].blank? ? impressions : impressions.where("created_at>=? and created_at<=?",options[:start_date],options[:end_date])
|
||||
options[:filter] == :all ? imps.count : imps.count(options[:filter], :distinct => true)
|
||||
end
|
||||
|
||||
def update_impressionist_counter_cache
|
||||
# cache_options = self.class.impressionist_counter_cache_options
|
||||
# column_name = cache_options[:column_name].to_sym
|
||||
# count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count
|
||||
# update_attribute(column_name, count)
|
||||
cache_options = self.class.impressionist_counter_cache_options
|
||||
column_name = cache_options[:column_name].to_sym
|
||||
update_attribute(column_name, self.send(cache_options[:column_name]) + 1)
|
||||
count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count
|
||||
old_count = send(column_name) || 0
|
||||
self.class.update_counters(id, column_name => (count - old_count))
|
||||
end
|
||||
|
||||
# OLD METHODS - DEPRECATE IN V0.5
|
||||
|
|
|
@ -7,6 +7,7 @@ module Impressionist
|
|||
def copy_config_file
|
||||
template 'impression.rb', 'config/initializers/impression.rb'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Use this hook to configure impressionist parameters
|
||||
Impressionist.setup do |config|
|
||||
# Define ORM. Could be :active_record (default) and :mongo_mapper
|
||||
# Define ORM. Could be :active_record (default), :mongo_mapper or :mongoid
|
||||
# config.orm = :active_record
|
||||
end
|
||||
|
|
10
vendor/impressionist/lib/impressionist/controllers/mongoid/impressionist_controller.rb
vendored
Normal file
10
vendor/impressionist/lib/impressionist/controllers/mongoid/impressionist_controller.rb
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
ImpressionistController::InstanceMethods.send(:define_method, :direct_create_statement) do |query_params={}|
|
||||
# creates a statment hash that contains default values for creating an impression.
|
||||
# if :impressionable_id is a valid ObjectId then convert it into one
|
||||
base = (defined? Moped) ? Moped::BSON : BSON
|
||||
query_params.reverse_merge!(
|
||||
:impressionable_type => controller_name.singularize.camelize,
|
||||
:impressionable_id=> !base::ObjectId.legal?(params[:id]) ? params[:id] : base::ObjectId.from_string(params[:id])
|
||||
)
|
||||
associative_create_statement(query_params)
|
||||
end
|
|
@ -5,7 +5,7 @@ module Impressionist
|
|||
class Engine < Rails::Engine
|
||||
initializer 'impressionist.model' do |app|
|
||||
require "#{root}/app/models/impressionist/impressionable.rb"
|
||||
if Impressionist.orm == :active_record
|
||||
if Impressionist.orm == :active_record && defined? ActiveRecord
|
||||
require "impressionist/models/active_record/impression.rb"
|
||||
require "impressionist/models/active_record/impressionist/impressionable.rb"
|
||||
ActiveRecord::Base.send(:include, Impressionist::Impressionable)
|
||||
|
@ -14,13 +14,16 @@ module Impressionist
|
|||
require "impressionist/models/mongo_mapper/impressionist/impressionable.rb"
|
||||
MongoMapper::Document.plugin Impressionist::Impressionable
|
||||
elsif Impressionist.orm == :mongoid
|
||||
require "impressionist/models/mongoid/impression.rb"
|
||||
require "impressionist/models/mongoid/impressionist/impressionable.rb"
|
||||
# Mongoid::Document Impressionist::Impressionable
|
||||
require 'impressionist/models/mongoid/impression.rb'
|
||||
require 'impressionist/models/mongoid/impressionist/impressionable.rb'
|
||||
Mongoid::Document.send(:include, Impressionist::Impressionable)
|
||||
end
|
||||
end
|
||||
|
||||
initializer 'impressionist.controller' do
|
||||
if Impressionist.orm == :mongoid
|
||||
require 'impressionist/controllers/mongoid/impressionist_controller.rb'
|
||||
end
|
||||
ActiveSupport.on_load(:action_controller) do
|
||||
include ImpressionistController::InstanceMethods
|
||||
extend ImpressionistController::ClassMethods
|
||||
|
|
|
@ -2,8 +2,12 @@ class Impression
|
|||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
|
||||
field :impressionable_type
|
||||
field :impressionable_id
|
||||
attr_accessible :impressionable_type, :impressionable_field, :impressionable_id, :user_id,
|
||||
:controller_name, :action_name, :view_name, :request_hash, :ip_address,
|
||||
:session_hash, :message, :referrer
|
||||
|
||||
belongs_to :impressionable, polymorphic: true
|
||||
|
||||
field :user_id
|
||||
field :controller_name
|
||||
field :action_name
|
||||
|
@ -14,26 +18,15 @@ class Impression
|
|||
field :message
|
||||
field :referrer
|
||||
|
||||
belongs_to :impressionable, :polymorphic => true
|
||||
|
||||
after_save :update_impressions_counter_cache
|
||||
|
||||
def self.impressionist_count(options={})
|
||||
options.reverse_merge!(:filter => :request_hash, :start_date => nil, :end_date => Time.now)
|
||||
imps = options[:start_date].blank? ? impressions : impressions.where(:created_at.gte => options[:start_date], :created_at.lte => options[:end_date])
|
||||
options[:filter] == :all ? imps.count : imps.distinct(options[:filter]).count
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_impressions_counter_cache
|
||||
if self.referrer
|
||||
impressionable_class = self.impressionable_type.constantize
|
||||
set_callback(:create, :after) do |doc|
|
||||
unless impressionable_id.nil?
|
||||
impressionable_class = doc.impressionable_type.constantize
|
||||
|
||||
if impressionable_class.impressionist_counter_cache_options
|
||||
resouce = impressionable_class.find(self.impressionable_id)
|
||||
resouce.try(:update_impressionist_counter_cache)
|
||||
resource = impressionable_class.find(doc.impressionable_id)
|
||||
resource.try(:update_impressionist_counter_cache)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -4,9 +4,49 @@ module Impressionist
|
|||
|
||||
module ClassMethods
|
||||
def is_impressionable(options={})
|
||||
has_many :impressions, :as => :impressionable, :dependent => :destroy
|
||||
@impressionist_cache_options = options[:counter_cache]
|
||||
has_many :impressions, as: :impressionable, dependent: :destroy
|
||||
@impressionist_cache_options = options[:counter_cache]
|
||||
if !@impressionist_cache_options.nil?
|
||||
opts = impressionist_counter_cache_options
|
||||
field opts[:column_name], type: Integer
|
||||
end
|
||||
end
|
||||
|
||||
def impressionist_counter_cache_options
|
||||
if @impressionist_cache_options
|
||||
options = { :column_name => :impressions_count, :unique => false }
|
||||
options.merge!(@impressionist_cache_options) if @impressionist_cache_options.is_a?(Hash)
|
||||
options
|
||||
end
|
||||
end
|
||||
|
||||
def impressionist_counter_caching?
|
||||
impressionist_counter_cache_options.present?
|
||||
end
|
||||
|
||||
def counter_caching?
|
||||
::ActiveSupport::Deprecation.warn("#counter_caching? is deprecated; please use #impressionist_counter_caching? instead")
|
||||
impressionist_counter_caching?
|
||||
end
|
||||
end
|
||||
|
||||
def impressionable?
|
||||
true
|
||||
end
|
||||
|
||||
def impressionist_count(options={})
|
||||
options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now)
|
||||
imps = options[:start_date].blank? ? impressions : impressions.between(created_at: options[:start_date]..options[:end_date])
|
||||
options[:filter] == :all ? imps.count : imps.where(options[:filter].ne => nil).count
|
||||
end
|
||||
|
||||
def update_impressionist_counter_cache
|
||||
cache_options = self.class.impressionist_counter_cache_options
|
||||
column_name = cache_options[:column_name].to_sym
|
||||
count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count
|
||||
old_count = send(column_name) || 0
|
||||
self.inc(column_name, (count - old_count))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -38,6 +38,13 @@ describe Impression do
|
|||
@widget.reload
|
||||
}.should change(@widget, :impressions_count).from(0).to(1)
|
||||
end
|
||||
|
||||
it "should not update the timestamp on the impressable" do
|
||||
lambda {
|
||||
@widget.impressions.create(:request_hash => 'abcd1234')
|
||||
@widget.reload
|
||||
}.should_not change(@widget, :updated_at)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
README.rdoc
|
||||
lib/**/*.rb
|
||||
bin/*
|
||||
features/**/*.feature
|
||||
LICENSE
|
|
@ -1,20 +0,0 @@
|
|||
Copyright (c) 2009 jugyo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,53 +0,0 @@
|
|||
sunspot_mongoid
|
||||
====
|
||||
|
||||
A Sunspot wrapper for Mongoid.
|
||||
|
||||
Install
|
||||
----
|
||||
|
||||
gem install sunspot_mongoid
|
||||
|
||||
Examples
|
||||
----
|
||||
|
||||
class Post
|
||||
include Mongoid::Document
|
||||
field :title
|
||||
|
||||
include Sunspot::Mongoid
|
||||
searchable do
|
||||
text :title
|
||||
end
|
||||
end
|
||||
|
||||
For Rails3
|
||||
----
|
||||
|
||||
### as gem:
|
||||
|
||||
add a gem to Gemfile as following,
|
||||
|
||||
gem 'sunspot_mongoid'
|
||||
|
||||
### as plugin:
|
||||
|
||||
add gems to Gemfile as following,
|
||||
|
||||
gem 'sunspot'
|
||||
gem 'sunspot_rails'
|
||||
|
||||
and install sunspot_mongoid as rails plugin,
|
||||
|
||||
rails plugin install git://github.com/jugyo/sunspot_mongoid.git
|
||||
|
||||
Links
|
||||
----
|
||||
|
||||
* [sunspot](http://github.com/outoftime/sunspot)
|
||||
* [sunspot_rails](http://github.com/outoftime/sunspot/tree/master/sunspot_rails/)
|
||||
|
||||
Copyright
|
||||
----
|
||||
|
||||
Copyright (c) 2010 jugyo. See LICENSE for details.
|
|
@ -1,57 +0,0 @@
|
|||
require 'rubygems'
|
||||
require 'rake'
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
Jeweler::Tasks.new do |gem|
|
||||
gem.name = "sunspot_mongoid"
|
||||
gem.summary = %Q{A Sunspot wrapper for Mongoid.}
|
||||
gem.description = %Q{A Sunspot wrapper for Mongoid that is like sunspot_rails.}
|
||||
gem.email = "jugyo.org@gmail.com"
|
||||
gem.homepage = "http://github.com/jugyo/sunspot_mongoid"
|
||||
gem.authors = ["jugyo"]
|
||||
gem.add_runtime_dependency "mongoid", ">= 0"
|
||||
gem.add_runtime_dependency "sunspot", ">= 1.1.0"
|
||||
gem.add_runtime_dependency "sunspot_rails", ">= 1.1.0"
|
||||
gem.add_development_dependency "shoulda", ">= 0"
|
||||
gem.add_development_dependency "rr", ">= 0"
|
||||
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
||||
end
|
||||
Jeweler::GemcutterTasks.new
|
||||
rescue LoadError
|
||||
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
||||
end
|
||||
|
||||
require 'rake/testtask'
|
||||
Rake::TestTask.new(:test) do |test|
|
||||
test.libs << 'lib' << 'test'
|
||||
test.pattern = 'test/**/test_*.rb'
|
||||
test.verbose = true
|
||||
end
|
||||
|
||||
begin
|
||||
require 'rcov/rcovtask'
|
||||
Rcov::RcovTask.new do |test|
|
||||
test.libs << 'test'
|
||||
test.pattern = 'test/**/test_*.rb'
|
||||
test.verbose = true
|
||||
end
|
||||
rescue LoadError
|
||||
task :rcov do
|
||||
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
||||
end
|
||||
end
|
||||
|
||||
task :test => :check_dependencies
|
||||
|
||||
task :default => :test
|
||||
|
||||
require 'rake/rdoctask'
|
||||
Rake::RDocTask.new do |rdoc|
|
||||
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
||||
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = "sunspot_mongoid #{version}"
|
||||
rdoc.rdoc_files.include('README*')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
|
@ -1 +0,0 @@
|
|||
0.4.1
|
|
@ -1,36 +0,0 @@
|
|||
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||
require 'sunspot_mongoid'
|
||||
|
||||
Mongoid.configure do |config|
|
||||
config.master = Mongo::Connection.new.db('sunspot-mongoid-test')
|
||||
end
|
||||
|
||||
# model
|
||||
class Post
|
||||
include Mongoid::Document
|
||||
field :title
|
||||
|
||||
include Sunspot::Mongoid
|
||||
searchable do
|
||||
text :title
|
||||
end
|
||||
end
|
||||
|
||||
# remove old indexes
|
||||
Post.destroy_all
|
||||
|
||||
# indexing
|
||||
Post.create(:title => 'foo')
|
||||
Post.create(:title => 'foo bar')
|
||||
Post.create(:title => 'bar baz')
|
||||
|
||||
# commit
|
||||
Sunspot.commit
|
||||
|
||||
# search
|
||||
search = Post.search do
|
||||
keywords 'foo'
|
||||
end
|
||||
search.each_hit_with_result do |hit, post|
|
||||
p post
|
||||
end
|
|
@ -1 +0,0 @@
|
|||
require 'sunspot_mongoid'
|
|
@ -1,49 +0,0 @@
|
|||
require 'sunspot'
|
||||
require 'mongoid'
|
||||
require 'sunspot/rails'
|
||||
|
||||
# == Examples:
|
||||
#
|
||||
# class Post
|
||||
# include Mongoid::Document
|
||||
# field :title
|
||||
#
|
||||
# include Sunspot::Mongoid
|
||||
# searchable do
|
||||
# text :title
|
||||
# end
|
||||
# end
|
||||
#
|
||||
module Sunspot
|
||||
module Mongoid
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
extend Sunspot::Rails::Searchable::ActsAsMethods
|
||||
Sunspot::Adapters::DataAccessor.register(DataAccessor, base)
|
||||
Sunspot::Adapters::InstanceAdapter.register(InstanceAdapter, base)
|
||||
end
|
||||
end
|
||||
|
||||
class InstanceAdapter < Sunspot::Adapters::InstanceAdapter
|
||||
def id
|
||||
@instance.id
|
||||
end
|
||||
end
|
||||
|
||||
class DataAccessor < Sunspot::Adapters::DataAccessor
|
||||
def load(id)
|
||||
criteria(id).first
|
||||
end
|
||||
|
||||
def load_all(ids)
|
||||
criteria(ids)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def criteria(id)
|
||||
@clazz.criteria.id(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1 +0,0 @@
|
|||
require 'sunspot/mongoid'
|
|
@ -1,67 +0,0 @@
|
|||
# Generated by jeweler
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{sunspot_mongoid}
|
||||
s.version = "0.4.1"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["jugyo"]
|
||||
s.date = %q{2011-03-04}
|
||||
s.description = %q{A Sunspot wrapper for Mongoid that is like sunspot_rails.}
|
||||
s.email = %q{jugyo.org@gmail.com}
|
||||
s.extra_rdoc_files = [
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
]
|
||||
s.files = [
|
||||
".document",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"Rakefile",
|
||||
"VERSION",
|
||||
"examples/example.rb",
|
||||
"init.rb",
|
||||
"lib/sunspot/mongoid.rb",
|
||||
"lib/sunspot_mongoid.rb",
|
||||
"sunspot_mongoid.gemspec",
|
||||
"test/helper.rb",
|
||||
"test/test_sunspot_mongoid.rb"
|
||||
]
|
||||
s.homepage = %q{http://github.com/jugyo/sunspot_mongoid}
|
||||
s.require_paths = ["lib"]
|
||||
s.rubygems_version = %q{1.6.0}
|
||||
s.summary = %q{A Sunspot wrapper for Mongoid.}
|
||||
s.test_files = [
|
||||
"examples/example.rb",
|
||||
"test/helper.rb",
|
||||
"test/test_sunspot_mongoid.rb"
|
||||
]
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
||||
s.add_runtime_dependency(%q<mongoid>, [">= 0"])
|
||||
s.add_runtime_dependency(%q<sunspot>, [">= 1.1.0"])
|
||||
s.add_runtime_dependency(%q<sunspot_rails>, [">= 1.1.0"])
|
||||
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
||||
s.add_development_dependency(%q<rr>, [">= 0"])
|
||||
else
|
||||
s.add_dependency(%q<mongoid>, [">= 0"])
|
||||
s.add_dependency(%q<sunspot>, [">= 1.1.0"])
|
||||
s.add_dependency(%q<sunspot_rails>, [">= 1.1.0"])
|
||||
s.add_dependency(%q<shoulda>, [">= 0"])
|
||||
s.add_dependency(%q<rr>, [">= 0"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<mongoid>, [">= 0"])
|
||||
s.add_dependency(%q<sunspot>, [">= 1.1.0"])
|
||||
s.add_dependency(%q<sunspot_rails>, [">= 1.1.0"])
|
||||
s.add_dependency(%q<shoulda>, [">= 0"])
|
||||
s.add_dependency(%q<rr>, [">= 0"])
|
||||
end
|
||||
end
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
require 'rubygems'
|
||||
require 'test/unit'
|
||||
require 'shoulda'
|
||||
require 'rr'
|
||||
|
||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||
require 'sunspot_mongoid'
|
||||
|
||||
class Test::Unit::TestCase
|
||||
include RR::Adapters::TestUnit
|
||||
end
|
|
@ -1,51 +0,0 @@
|
|||
require 'helper'
|
||||
|
||||
#
|
||||
# NOTE: I think tests are too few...
|
||||
#
|
||||
class TestSunspotMongoid < Test::Unit::TestCase
|
||||
class Foo
|
||||
include Mongoid::Document
|
||||
field :title
|
||||
|
||||
include Sunspot::Mongoid
|
||||
searchable do
|
||||
text :title
|
||||
end
|
||||
end
|
||||
|
||||
class Bar
|
||||
include Mongoid::Document
|
||||
field :title
|
||||
|
||||
include Sunspot::Mongoid
|
||||
searchable(:auto_index => false, :auto_remove => false) do
|
||||
text :title
|
||||
end
|
||||
end
|
||||
|
||||
context 'default' do
|
||||
should 'sunspot_options is specified' do
|
||||
assert Foo.sunspot_options == {:include => []}
|
||||
assert Bar.sunspot_options == {:auto_index=>false, :auto_remove=>false, :include=>[]}
|
||||
end
|
||||
|
||||
should 'be called Sunspot.setup when call Foo.searchable' do
|
||||
mock(Sunspot).setup(Foo)
|
||||
Foo.searchable
|
||||
end
|
||||
|
||||
should 'get as text_fields from Sunspot::Setup' do
|
||||
text_field = Sunspot::Setup.for(Foo).all_text_fields.first
|
||||
assert text_field.type == Sunspot::Type::TextType.instance
|
||||
assert text_field.name == :title
|
||||
end
|
||||
|
||||
should 'search' do
|
||||
options = {}
|
||||
mock.proxy(Foo).solr_execute_search(options)
|
||||
mock(Sunspot).new_search(Foo) { mock(Object.new).execute }
|
||||
Foo.search(options)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue