csdn-tire 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,54 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x
3
+ #
4
+ # https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb
5
+ #
6
+
7
+ module URI
8
+ TBLENCWWWCOMP_ = {} # :nodoc:
9
+ 256.times do |i|
10
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
11
+ end
12
+ TBLENCWWWCOMP_[' '] = '+'
13
+ TBLENCWWWCOMP_.freeze
14
+ TBLDECWWWCOMP_ = {} # :nodoc:
15
+ 256.times do |i|
16
+ h, l = i>>4, i&15
17
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
18
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
19
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
20
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
21
+ end
22
+ TBLDECWWWCOMP_['+'] = ' '
23
+ TBLDECWWWCOMP_.freeze
24
+
25
+ # Encode given +s+ to URL-encoded form data.
26
+ #
27
+ # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
28
+ # (ASCII space) to + and converts others to %XX.
29
+ #
30
+ # This is an implementation of
31
+ # http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
32
+ #
33
+ # See URI.decode_www_form_component, URI.encode_www_form
34
+ def self.encode_www_form_component(s)
35
+ str = s.to_s
36
+ if RUBY_VERSION < "1.9" && $KCODE =~ /u/i
37
+ str.gsub(/([^ a-zA-Z0-9_.-]+)/) do
38
+ '%' + $1.unpack('H2' * Rack::Utils.bytesize($1)).join('%').upcase
39
+ end.tr(' ', '+')
40
+ else
41
+ str.gsub(/[^*\-.0-9A-Z_a-z]/) {|m| TBLENCWWWCOMP_[m]}
42
+ end
43
+ end
44
+
45
+ # Decode given +str+ of URL-encoded form data.
46
+ #
47
+ # This decods + to SP.
48
+ #
49
+ # See URI.encode_www_form_component, URI.decode_www_form
50
+ def self.decode_www_form_component(str, enc=nil)
51
+ raise ArgumentError, "invalid %-encoding (#{str})" unless /\A(?:%[0-9a-fA-F]{2}|[^%])*\z/ =~ str
52
+ str.gsub(/\+|%[0-9a-fA-F]{2}/) {|m| TBLDECWWWCOMP_[m]}
53
+ end
54
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'time'
3
+
4
+ class Array
5
+ def to_json(options=nil)
6
+ MultiJson.encode(self)
7
+ end unless method_defined? :to_json
8
+ end
9
+
10
+ class Hash
11
+ def to_json(options=nil)
12
+ MultiJson.encode(self)
13
+ end unless method_defined? :to_json
14
+
15
+ alias_method :to_indexed_json, :to_json
16
+ end
17
+
18
+ class Time
19
+ def to_json(options=nil)
20
+ %Q/"#{self.iso8601}"/
21
+ end
22
+ end
@@ -0,0 +1,80 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ class SearchRequestFailed < StandardError; end
4
+
5
+ class Search
6
+
7
+ attr_reader :payload, :payload_hash, :indices
8
+
9
+ def initialize(indices, types, payload)
10
+ @indices = Array(indices)
11
+ @types = Array(types).map { |type| Utils.escape(type) }
12
+ if payload.is_a?(String)
13
+ @payload = payload
14
+ else
15
+ @payload_hash = payload
16
+ end
17
+
18
+ @path = ['/', @indices.join(','), @types.join(','), '_search'].compact.join('/').squeeze('/')
19
+ end
20
+
21
+ def results
22
+ @json || (perform; @json)
23
+ end
24
+
25
+ def response
26
+ @response || (perform; @response)
27
+ end
28
+
29
+ def url
30
+ Configuration.url + @path
31
+ end
32
+
33
+ def perform
34
+ @response = Configuration.client.get(self.url, self.payload)
35
+ if @response.failure?
36
+ STDERR.puts "[REQUEST FAILED] #{self.to_curl}\n"
37
+ raise SearchRequestFailed, @response.to_s
38
+ end
39
+ @json = MultiJson.decode(@response.body)
40
+ return @json
41
+ ensure
42
+ logged
43
+ end
44
+
45
+ def to_curl
46
+ %Q|curl -X GET #{url} -d '#{payload}'|
47
+ end
48
+
49
+ def payload
50
+ @payload || MultiJson.encode(@payload_hash)
51
+ end
52
+
53
+ def to_hash
54
+ @hash_payload ||= MultiJson.decode(payload)
55
+ end
56
+
57
+ def logged(error=nil)
58
+ if Configuration.logger
59
+
60
+ Configuration.logger.log_request '_search', indices, to_curl
61
+
62
+ code = @response.code rescue nil
63
+
64
+ if Configuration.logger.level.to_s == 'debug'
65
+ # FIXME: Depends on RestClient implementation
66
+ body = if @json
67
+ defined?(Yajl) ? Yajl::Encoder.encode(@json, :pretty => true) : MultiJson.encode(@json)
68
+ else
69
+ @response.body rescue nil
70
+ end
71
+ else
72
+ body = ''
73
+ end
74
+
75
+ Configuration.logger.log_response code || 'N/A', "N/A", body || 'N/A'
76
+ end
77
+ end
78
+
79
+ end
80
+ end
data/lib/tire/state.rb ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ class State
4
+ include Utils
5
+
6
+ def initialize
7
+
8
+ end
9
+
10
+ def url
11
+ "#{Configuration.url}/cluster/_state"
12
+ end
13
+
14
+ def info(more = false)
15
+ desc_url = more ? "#{url}?more=true" : "#{url}?more=false"
16
+ @response = Configuration.client.get(desc_url)
17
+ if @response.success?
18
+ MultiJson.decode(@response.body)
19
+ else
20
+ []
21
+ end
22
+ ensure
23
+ curl = %Q|curl -X GET #{desc_url}|
24
+ logged('CLUSTER_STATE', curl)
25
+ end
26
+ end
27
+ end
data/lib/tire/utils.rb ADDED
@@ -0,0 +1,40 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'uri'
3
+
4
+ module Tire
5
+ module Utils
6
+
7
+ def escape(s)
8
+ URI.encode_www_form_component(s.to_s)
9
+ end
10
+
11
+ def unescape(s)
12
+ s = s.to_s.respond_to?(:force_encoding) ? s.to_s.force_encoding(Encoding::UTF_8) : s.to_s
13
+ URI.decode_www_form_component(s)
14
+ end
15
+
16
+ def logged(endpoint='/', curl='')
17
+ if Configuration.logger
18
+ error = $!
19
+
20
+ Configuration.logger.log_request endpoint, @name, curl
21
+
22
+ code = @response ? @response.code : error.class rescue 200
23
+
24
+ if Configuration.logger.level.to_s == 'debug'
25
+ body = if @response
26
+ defined?(Yajl) ? Yajl::Encoder.encode(@response.body, :pretty => true) : MultiJson.encode(@response.body)
27
+ else
28
+ error.message rescue ''
29
+ end
30
+ else
31
+ body = ''
32
+ end
33
+
34
+ Configuration.logger.log_response code, nil, body
35
+ end
36
+ end
37
+
38
+ module_function :escape, :unescape
39
+ end
40
+ end
@@ -0,0 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ VERSION = "0.5"
4
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'test_helper'
3
+
4
+ module Tire
5
+
6
+ class CountIntegrationTest < Test::Unit::TestCase
7
+ include Test::Integration
8
+
9
+ context "count" do
10
+ should "count results" do
11
+ setup_bulk
12
+ @index.refresh
13
+ count = Tire.count(INDEX, TYPE, '{"query":{"text":{"title":"java"}},"size":4,"from":0}')
14
+ num = count.results
15
+ assert_kind_of Integer, num
16
+ assert_equal 6, num
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,58 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'test_helper'
3
+
4
+ module Tire
5
+
6
+ class IndexIntegrationTest < Test::Unit::TestCase
7
+ include Test::Integration
8
+
9
+ context "index" do
10
+
11
+ should "regist_shard" do
12
+ assert @index.regist_shard(6)
13
+ end
14
+
15
+ should "not regist exist index" do
16
+ @index.regist_shard(6)
17
+ assert !@index.regist_shard(6)
18
+ end
19
+
20
+ should "delete index" do
21
+ assert @index.delete
22
+ end
23
+
24
+ should "get shard info" do
25
+ @index.regist_shard(6)
26
+ assert_kind_of Array, @index.shard_info
27
+ assert !@index.shard_info.empty?
28
+ end
29
+
30
+ should "create mapping" do
31
+ assert setup_mapping
32
+ end
33
+
34
+ should "get mapping info" do
35
+ setup_mapping
36
+ assert_kind_of Hash, @index.mapping(TYPE)
37
+ assert_not_nil @index.mapping(TYPE)[TYPE]
38
+ end
39
+
40
+ should "bulk insert" do
41
+ assert setup_bulk
42
+ end
43
+
44
+ should "flush index" do
45
+ setup_bulk
46
+ assert @index.flush
47
+ end
48
+
49
+ should "refresh index" do
50
+ setup_bulk
51
+ assert @index.refresh
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'test_helper'
3
+
4
+ module Tire
5
+
6
+ class SearchIntegrationTest < Test::Unit::TestCase
7
+ include Test::Integration
8
+
9
+ context "search" do
10
+ should "search results" do
11
+ setup_bulk
12
+ @index.refresh
13
+ search = Tire.search(INDEX, TYPE, '{"query":{"text":{"title":"java"}},"size":4,"from":0}')
14
+ results = search.results
15
+ assert_kind_of Hash, results
16
+ assert results["total"] > 0
17
+ assert_kind_of Array, results["hits"]
18
+ assert_equal 6, results["total"]
19
+ assert_equal 4, results["hits"].size
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'test_helper'
3
+
4
+ module Tire
5
+
6
+ class StateIntegrationTest < Test::Unit::TestCase
7
+ include Test::Integration
8
+
9
+ context "state" do
10
+ should "get short state" do
11
+ assert_kind_of Array, Tire.state.info
12
+ assert_kind_of Hash, Tire.state.info.first
13
+ end
14
+
15
+ should "get more state" do
16
+ assert_kind_of Array, Tire.state.info(true)
17
+ assert_kind_of Hash, Tire.state.info(true).first
18
+ assert_not_nil Tire.state.info(true).first["blog"]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,104 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+
5
+ require 'test/unit'
6
+
7
+ require 'yajl'
8
+ #require 'yajl/json_gem'
9
+
10
+ require 'shoulda'
11
+ require 'turn/autorun' unless defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
12
+ require 'mocha'
13
+
14
+ require 'tire'
15
+
16
+ class Test::Unit::TestCase
17
+
18
+ def mock_response(body, code=200, headers={})
19
+ Tire::HTTP::Response.new(body, code, headers)
20
+ end
21
+
22
+ end
23
+
24
+ module Test::Integration
25
+ URL = "http://192.168.6.35:9400"
26
+ INDEX = "articles_test"
27
+ TYPE = "type_test"
28
+
29
+ def setup
30
+ ENV['ELASTICSEARCH_URL'] = URL
31
+ @index = Tire.index(INDEX)
32
+ end
33
+
34
+ def setup_shard
35
+ @index.regist_shard(6)
36
+ end
37
+
38
+ def setup_mapping
39
+ mapping = {TYPE => {"_source"=>{"enabled"=>false},
40
+ "properties"=>
41
+ {"title"=>
42
+ {"type"=>"string",
43
+ "term_vector"=>"with_positions_offsets",
44
+ "boost"=>2.0},
45
+ "body"=>{"type"=>"string", "term_vector"=>"with_positions_offsets"},
46
+ "username"=>{"type"=>"string", "index"=>"not_analyzed", "store"=>"no"},
47
+ "id"=>
48
+ {"type"=>"integer", "index"=>"not_analyzed", "include_in_all"=>false},
49
+ "created_at"=>
50
+ {"type"=>"integer", "index"=>"not_analyzed", "include_in_all"=>false}
51
+ }
52
+ }
53
+ }
54
+ setup_shard
55
+ @index.create_mapping(TYPE, mapping)
56
+ end
57
+
58
+ def setup_bulk
59
+ doc = [
60
+ {"title"=>"java 是好东西",
61
+ "body"=>"hey java",
62
+ "id"=>"1",
63
+ "username"=>"jack",
64
+ "created_at"=>2007072323},
65
+ {"title"=>"this java cool",
66
+ "body"=>"hey java",
67
+ "id"=>"2",
68
+ "created_at"=>2009072323,
69
+ "username"=>"robbin"},
70
+ {"title"=>"this is java cool",
71
+ "body"=>"hey java",
72
+ "id"=>"3",
73
+ "created_at"=>2010072323,
74
+ "username"=>"www"},
75
+ {"title"=>"java is really cool",
76
+ "body"=>"hey java",
77
+ "id"=>"4",
78
+ "created_at"=>2007062323,
79
+ "username"=>"google"},
80
+ {"title"=>"this is wakak cool",
81
+ "body"=>"hey java",
82
+ "id"=>"5",
83
+ "created_at"=>2007062323,
84
+ "username"=>"jackde"},
85
+ {"title"=>"this is java cool",
86
+ "body"=>"hey java",
87
+ "id"=>"6",
88
+ "created_at"=>2007012323,
89
+ "username"=>"jackk wa"},
90
+ {"title"=>"this java really cool",
91
+ "body"=>"hey java",
92
+ "id"=>"7",
93
+ "created_at"=>2002072323,
94
+ "username"=>"william"}
95
+ ]
96
+ setup_mapping
97
+ @index.bulk(TYPE, doc)
98
+ end
99
+
100
+
101
+ def teardown
102
+ ::RestClient.delete "#{URL}/#{INDEX}" rescue nil
103
+ end
104
+ end