rdf-mongo 0.1.9.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -15,7 +15,26 @@ It should also be noted that prior to 1.0, there are no guarantees of backwards
15
15
  You'll need the 'mongo', 'rdf', 'rdf-spec', and 'rspec' libraries. The easiest way to install these is via RubyGems.
16
16
 
17
17
  $ sudo gem install mongo rdf rdf-spec rspec rdf-mongo
18
-
18
+
19
+ ## Implementation Notes
20
+
21
+ RDF Statements are stored as individual documents within MONGO using the following BSON:
22
+
23
+ {
24
+ "s": RDF::Value
25
+ "st": one of :u or :n
26
+ "p": RDF::URI
27
+ "pt": must be :n
28
+ "o" RDF::Value
29
+ "ot" one of :u, :n, :l, :ll, or :lt
30
+ "ol" Language symbol or RDF::URI
31
+ "c" RDF::Value or false
32
+ "ct": one of :u, :n, :l, :ll, :lt or :default
33
+ }
34
+
35
+ An alternative that may be examined at a later point would be to use a representation based on RDF/JSON,
36
+ or JSON-LD. This would save documents based on a common subject with
37
+ one more more predicates having one or more types.
19
38
 
20
39
  ### Support
21
40
 
@@ -23,6 +42,7 @@ Please post questions or feedback to the [W3C-ruby-rdf mailing list][].
23
42
 
24
43
  ### Authors
25
44
  * [Pius Uzamere][] | <pius@alum.mit.edu> | <http://github.com/pius> | <http://pius.me>
45
+ * [Gregg Kellogg][] | <gregg@greggkellogg.net> | <http://github.com/gkellogg> | <http://greggkellogg.net>
26
46
 
27
47
  ### Thank you
28
48
 
@@ -34,3 +54,4 @@ MIT License
34
54
 
35
55
  [W3C-ruby-rdf mailing list]: http://lists.w3.org/Archives/Public/public-rdf-ruby/
36
56
  [Pius Uzamere]: http://pius.me
57
+ [Gregg Kellogg]: http://greggkellogg.net/me
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.9.1
1
+ 1.0.3
@@ -0,0 +1,20 @@
1
+ module RDF::Mongo
2
+ module VERSION
3
+ VERSION_FILE = File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "VERSION")
4
+ MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chomp.split(".")
5
+
6
+ STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
7
+
8
+ ##
9
+ # @return [String]
10
+ def self.to_s() STRING end
11
+
12
+ ##
13
+ # @return [String]
14
+ def self.to_str() STRING end
15
+
16
+ ##
17
+ # @return [Array(Integer, Integer, Integer)]
18
+ def self.to_a() [MAJOR, MINOR, TINY] end
19
+ end
20
+ end
data/lib/rdf/mongo.rb CHANGED
@@ -2,26 +2,23 @@ require 'rdf'
2
2
  require 'enumerator'
3
3
  require 'mongo'
4
4
 
5
- module Mongo
6
- class Cursor
7
- def rdf_each(&block)
8
- if block_given?
9
- each {|statement| block.call(RDF::Statement.from_mongo(statement)) }
10
- else
11
- self
12
- end
13
- end
14
- end
15
- end
16
-
17
5
  module RDF
18
6
  class Statement
7
+ ##
8
+ # Creates a BSON representation of the statement.
9
+ # @return [Hash]
19
10
  def to_mongo
20
- self.to_hash.merge({:context => self.context}).inject({}) { |hash, (place_in_statement, entity)|
11
+ self.to_hash.inject({}) do |hash, (place_in_statement, entity)|
21
12
  hash.merge(RDF::Mongo::Conversion.to_mongo(entity, place_in_statement))
22
- }
13
+ end
23
14
  end
24
15
 
16
+ ##
17
+ # Create BSON for a statement representation. Note that if the statement has no context,
18
+ # a value of `false` will be used to indicate the default context
19
+ #
20
+ # @param [RDF::Statement] statement
21
+ # @return [Hash] Generated BSON representation of statement.
25
22
  def self.from_mongo(statement)
26
23
  RDF::Statement.new(
27
24
  :subject => RDF::Mongo::Conversion.from_mongo(statement['s'], statement['st'], statement['sl']),
@@ -31,21 +28,46 @@ module RDF
31
28
  end
32
29
  end
33
30
 
34
- module Mongo
31
+ module Mongo
32
+ autoload :VERSION, "rdf/mongo/version"
33
+
35
34
  class Conversion
36
- #TODO: Add support for other types of entities
37
-
35
+ ##
36
+ # Translate an RDF::Value type to BSON key/value pairs.
37
+ #
38
+ # @param [RDF::Value, Symbol, false, nil] value
39
+ # URI, BNode or Literal. May also be a Variable or Symbol to indicate
40
+ # a pattern for a named context, or `false` to indicate the default context.
41
+ # A value of `nil` indicates a pattern that matches any value.
42
+ # @param [:subject, :predicate, :object, :context] place_in_statement
43
+ # Position within statement.
44
+ # @return [Hash] BSON representation of the statement
38
45
  def self.to_mongo(value, place_in_statement)
39
46
  case value
40
47
  when RDF::URI
41
48
  v, k = value.to_s, :u
42
49
  when RDF::Literal
43
- v, k, ll = value.value, :l, value.language
50
+ if value.has_language?
51
+ v, k, ll = value.value, :ll, value.language.to_s
52
+ elsif value.has_datatype?
53
+ v, k, ll = value.value, :lt, value.datatype.to_s
54
+ else
55
+ v, k, ll = value.value, :l, nil
56
+ end
57
+ when RDF::Node
58
+ v, k = value.id.to_s, :n
59
+ when RDF::Query::Variable, Symbol
60
+ # Returns anything other than the default context
61
+ v, k = nil, {"$ne" => :default}
62
+ when false
63
+ # Used for the default context
64
+ v, k = false, :default
44
65
  when nil
45
66
  v, k = nil, nil
46
67
  else
47
68
  v, k = value.to_s, :u
48
69
  end
70
+ v = nil if v == ''
49
71
 
50
72
  case place_in_statement
51
73
  when :subject
@@ -57,49 +79,60 @@ module RDF
57
79
  when :context
58
80
  t, k1, lt = :ct, :c, :cl
59
81
  end
60
- h = {k1 => (v == '' ? nil : v), t => (k == '' ? nil : k), lt => ll}
82
+ h = {k1 => v, t => k, lt => ll}
61
83
  h.delete_if {|k,v| h[k].nil?}
62
84
  end
63
85
 
64
- def self.from_mongo(value, value_type = :u, lang = nil)
86
+ ##
87
+ # Translate an BSON positional reference to an RDF Value.
88
+ #
89
+ # @return [RDF::Value]
90
+ def self.from_mongo(value, value_type = :u, literal_extra = nil)
65
91
  case value_type
66
92
  when :u
67
- RDF::URI.new(value)
93
+ RDF::URI.intern(value)
94
+ when :ll
95
+ RDF::Literal.new(value, :language => literal_extra.to_sym)
96
+ when :lt
97
+ RDF::Literal.new(value, :datatype => RDF::URI.intern(literal_extra))
68
98
  when :l
69
- RDF::Literal.new(value, :language => lang)
99
+ RDF::Literal.new(value)
100
+ when :n
101
+ @nodes ||= {}
102
+ @nodes[value] ||= RDF::Node.new(value)
103
+ when :default
104
+ nil # The default context returns as nil, although it's queried as false.
70
105
  end
71
106
  end
72
107
  end
73
-
74
-
108
+
75
109
  class Repository < ::RDF::Repository
76
-
77
- def self.load(filenames, options = {:host => 'localhost', :port => 27017, :db => 'quadb'}, &block)
78
- self.new(options) do |repository|
79
- [filenames].flatten.each do |filename|
80
- repository.load(filename, options)
81
- end
110
+ # The Mongo database instance
111
+ # @!attribute [r] db
112
+ # @return [Mongo::DB]
113
+ attr_reader :db
82
114
 
83
- if block_given?
84
- case block.arity
85
- when 1 then block.call(repository)
86
- else repository.instance_eval(&block)
87
- end
88
- end
89
- end
90
- end
91
-
92
- def db
93
- @db
94
- end
115
+ # The collection used for storing quads
116
+ # @!attribute [r] coll
117
+ # @return [Mongo::Collection]
118
+ attr_reader :coll
95
119
 
96
- def coll
97
- @coll
98
- end
99
-
100
- def initialize(options = {:host => 'localhost', :port => 27017, :db => 'quadb'})
120
+ ##
121
+ # Initializes this repository instance.
122
+ #
123
+ # @param [Hash{Symbol => Object}] options
124
+ # @option options [URI, #to_s] :uri (nil)
125
+ # @option options [String, #to_s] :title (nil)
126
+ # @option options [String] :host
127
+ # @option options [Integer] :port
128
+ # @option options [String] :db
129
+ # @option options [String] :collection ('quads')
130
+ # @yield [repository]
131
+ # @yieldparam [Repository] repository
132
+ def initialize(options = {}, &block)
133
+ options = {:host => 'localhost', :port => 27017, :db => 'quadb', :collection => 'quads'}.merge(options)
101
134
  @db = ::Mongo::Connection.new(options[:host], options[:port]).db(options[:db])
102
- @coll = @db['quads']
135
+ @coll = @db[options[:collection]]
103
136
  @coll.create_index("s")
104
137
  @coll.create_index("p")
105
138
  @coll.create_index("o")
@@ -107,71 +140,104 @@ module RDF
107
140
  @coll.create_index([["s", ::Mongo::ASCENDING], ["p", ::Mongo::ASCENDING]])
108
141
  @coll.create_index([["s", ::Mongo::ASCENDING], ["o", ::Mongo::ASCENDING]])
109
142
  @coll.create_index([["p", ::Mongo::ASCENDING], ["o", ::Mongo::ASCENDING]])
110
- end
111
-
112
- # @see RDF::Enumerable#each.
113
- def each(&block)
114
- if block_given?
115
- statements = @coll.find()
116
- statements.each {|statement| block.call(RDF::Statement.from_mongo(statement)) }
117
- else
118
- statements = @coll.find()
119
- enumerator!.new(statements,:rdf_each)
120
- end
143
+ super(options, &block)
121
144
  end
122
145
 
123
146
  # @see RDF::Mutable#insert_statement
147
+ def supports?(feature)
148
+ case feature.to_sym
149
+ when :context then true
150
+ else false
151
+ end
152
+ end
153
+
124
154
  def insert_statement(statement)
125
- @coll.update(statement.to_mongo, statement.to_mongo, :upsert => true)
155
+ st_mongo = statement.to_mongo
156
+ st_mongo[:ct] ||= :default # Indicate statement is in the default context
157
+ #puts "insert statement: #{st_mongo.inspect}"
158
+ @coll.update(st_mongo, st_mongo, :upsert => true)
126
159
  end
127
160
 
128
161
  # @see RDF::Mutable#delete_statement
129
162
  def delete_statement(statement)
130
- @coll.remove(statement.to_mongo)
163
+ case statement.context
164
+ when nil
165
+ @coll.remove(statement.to_mongo.merge('ct'=>:default))
166
+ else
167
+ @coll.remove(statement.to_mongo)
168
+ end
131
169
  end
132
-
170
+
171
+ ##
172
+ # @private
173
+ # @see RDF::Durable#durable?
174
+ def durable?; true; end
175
+
176
+ ##
177
+ # @private
178
+ # @see RDF::Countable#empty?
179
+ def empty?; @coll.count == 0; end
180
+
181
+ ##
182
+ # @private
183
+ # @see RDF::Countable#count
133
184
  def count
134
185
  @coll.count
135
186
  end
136
-
137
- def query(pattern, &block)
138
- case pattern
139
- when RDF::Statement
140
- query(pattern.to_hash)
141
- when Array
142
- query(RDF::Statement.new(*pattern))
143
- when Hash
144
- statements = query_hash(pattern)
145
- the_statements = statements || []
146
- case block_given?
147
- when true
148
- the_statements.each {|s| block.call(RDF::Statement.from_mongo(s))}
149
- else
150
- def the_statements.each(&block)
151
- if block_given?
152
- super {|statement| block.call(RDF::Statement.from_mongo(statement)) }
153
- else
154
- enumerator!.new(the_statements,:rdf_each)
155
- end
156
- end
157
-
158
- def the_statements.size
159
- count
160
- end
161
- s = the_statements
187
+
188
+ def clear_statements
189
+ @coll.remove
190
+ end
191
+
192
+ ##
193
+ # @private
194
+ # @see RDF::Enumerable#has_statement?
195
+ def has_statement?(statement)
196
+ !!@coll.find_one(statement.to_mongo)
197
+ end
198
+ ##
199
+ # @private
200
+ # @see RDF::Enumerable#each_statement
201
+ def each_statement(&block)
202
+ @nodes = {} # reset cache. FIXME this should probably be in Node.intern
203
+ if block_given?
204
+ @coll.find() do |cursor|
205
+ cursor.each do |data|
206
+ block.call(RDF::Statement.from_mongo(data))
162
207
  end
163
- else
164
- super(pattern)
208
+ end
165
209
  end
210
+ enum_statement
166
211
  end
167
-
168
- def query_hash(hash)
169
- return @coll.find if hash.empty?
170
- h = RDF::Statement.new(hash).to_mongo
171
- @coll.find(h)
212
+ alias_method :each, :each_statement
213
+
214
+ ##
215
+ # @private
216
+ # @see RDF::Enumerable#has_context?
217
+ def has_context?(value)
218
+ !!@coll.find_one(RDF::Mongo::Conversion.to_mongo(value, :context))
172
219
  end
173
-
174
-
220
+
221
+ protected
222
+
223
+ ##
224
+ # @private
225
+ # @see RDF::Queryable#query_pattern
226
+ # @see RDF::Query::Pattern
227
+ def query_pattern(pattern, &block)
228
+ @nodes = {} # reset cache. FIXME this should probably be in Node.intern
229
+
230
+ # A pattern context of `false` is used to indicate the default context
231
+ pm = pattern.to_mongo
232
+ pm.merge!(:c => nil, :ct => :default) if pattern.context == false
233
+ #puts "query using #{pm.inspect}"
234
+ @coll.find(pm) do |cursor|
235
+ cursor.each do |data|
236
+ block.call(RDF::Statement.from_mongo(data))
237
+ end
238
+ end
239
+ end
240
+
175
241
  private
176
242
 
177
243
  def enumerator! # @private
metadata CHANGED
@@ -1,137 +1,149 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rdf-mongo
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 9
9
- - 1
10
- version: 0.1.9.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.3
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Pius Uzamere
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2010-04-27 00:00:00 -04:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: rdf
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
23
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- - 1
31
- - 8
32
- version: 0.1.8
33
- type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: rdf-spec
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mongo
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.5.1
38
+ type: :runtime
37
39
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- segments:
43
- - 0
44
- - 1
45
- - 8
46
- version: 0.1.8
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.5.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdf-spec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '1.0'
47
54
  type: :development
48
- version_requirements: *id002
49
- - !ruby/object:Gem::Dependency
50
- name: rspec
51
55
  prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- segments:
57
- - 1
58
- - 3
59
- - 0
60
- version: 1.3.0
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 2.12.0
61
70
  type: :development
62
- version_requirements: *id003
63
- - !ruby/object:Gem::Dependency
64
- name: yard
65
71
  prerelease: false
66
- requirement: &id004 !ruby/object:Gem::Requirement
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- segments:
71
- - 0
72
- - 5
73
- - 3
74
- version: 0.5.3
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 2.12.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: yard
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.8.3
75
86
  type: :development
76
- version_requirements: *id004
77
- - !ruby/object:Gem::Dependency
78
- name: addressable
79
87
  prerelease: false
80
- requirement: &id005 !ruby/object:Gem::Requirement
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- segments:
85
- - 2
86
- - 1
87
- - 1
88
- version: 2.1.1
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.8.3
94
+ - !ruby/object:Gem::Dependency
95
+ name: addressable
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 2.3.2
89
102
  type: :runtime
90
- version_requirements: *id005
91
- description: rdf-mongo is a storage adapter for integrating MongoDB and rdf.rb, a Ruby library for working with Resource Description Framework (RDF) data.
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 2.3.2
110
+ description: rdf-mongo is a storage adapter for integrating MongoDB and rdf.rb, a
111
+ Ruby library for working with Resource Description Framework (RDF) data.
92
112
  email: pius@alum.mit.edu
93
113
  executables: []
94
-
95
114
  extensions: []
96
-
97
115
  extra_rdoc_files: []
98
-
99
- files:
116
+ files:
100
117
  - LICENSE
101
118
  - VERSION
102
119
  - README.md
120
+ - lib/rdf/mongo/version.rb
103
121
  - lib/rdf/mongo.rb
104
- has_rdoc: false
105
- homepage: http://github.com/pius/rdf-mongo
106
- licenses:
122
+ homepage: http://ruby-rdf.github.com/rdf-mongo
123
+ licenses:
107
124
  - MIT License
108
125
  post_install_message: Have fun! :)
109
126
  rdoc_options: []
110
-
111
- require_paths:
127
+ require_paths:
112
128
  - lib
113
- required_ruby_version: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- segments:
118
- - 1
119
- - 8
120
- - 6
121
- version: 1.8.6
122
- required_rubygems_version: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- segments:
127
- - 0
128
- version: "0"
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: 1.8.7
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
129
141
  requirements: []
130
-
131
142
  rubyforge_project:
132
- rubygems_version: 1.3.6
143
+ rubygems_version: 1.8.24
133
144
  signing_key:
134
145
  specification_version: 3
135
- summary: A storage adapter for integrating MongoDB and rdf.rb, a Ruby library for working with Resource Description Framework (RDF) data.
136
- test_files:
137
- - spec/mongo_repository.spec
146
+ summary: A storage adapter for integrating MongoDB and rdf.rb, a Ruby library for
147
+ working with Resource Description Framework (RDF) data.
148
+ test_files: []
149
+ has_rdoc: false
@@ -1,24 +0,0 @@
1
- $:.unshift File.dirname(__FILE__) + "/../lib/"
2
-
3
- require 'rdf'
4
- require 'rdf/spec/repository'
5
- require 'rdf/mongo'
6
- require 'enumerator'
7
-
8
- describe RDF::Mongo::Repository do
9
- context "Mongo RDF Repository" do
10
- before :each do
11
- @repository = RDF::Mongo::Repository.new() # TODO: Do you need constructor arguments?
12
- @repository.coll.drop
13
- end
14
-
15
- after :each do
16
- @repository.coll.drop
17
- end
18
-
19
- # @see lib/rdf/spec/repository.rb in RDF-spec
20
- it_should_behave_like RDF_Repository
21
- end
22
-
23
- end
24
-