Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 716 lines (442 sloc) 18.893 kb
4ccfae7 @andreasronge try to get a very simple gemspec to work
andreasronge authored
1 = Neo4j
5706e66 added more docs
andreasr authored
2
e477cf3 @andreasronge fixed some lucene bugs, update docs
andreasronge authored
3 Neo4j is a graph database framework for JRuby.
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
4
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
5 It provides:
6 * Mapping of ruby objects to nodes in networks rather than in tables.
7 * Storage of ruby object to a file system.
8 * Fast traversal of relationships between nodes in a hugh node space.
9 * Transaction with rollbacks support.
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
10 * Indexing and querying of ruby objects.
5706e66 added more docs
andreasr authored
11
bd948f7 @andreasronge lucene dsl queries can now be used from Neo4j::Node
andreasronge authored
12 Neo4j consist of two modules: Neo4j and Lucene.
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
13 Neo4j depends on the Lucene module.
14
bd948f7 @andreasronge lucene dsl queries can now be used from Neo4j::Node
andreasronge authored
15 It uses two powerful java libraries:
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
16 * Neo4J (http://www.neo4j.org/) - for persistance and traversal of the graph
17 * Lucene (http://lucene.apache.org/java/docs/index.html) for quering and indexing.
5706e66 added more docs
andreasr authored
18
1f7e9fc @andreasronge update README with installation instruction
andreasronge authored
19 == Installation
20
0b28379 @andreasronge released to rubyforge gem repository
andreasronge authored
21 Neo4j exists as a gem at rubyforge
1f7e9fc @andreasronge update README with installation instruction
andreasronge authored
22 To install it please type:
23
0b28379 @andreasronge released to rubyforge gem repository
andreasronge authored
24 gem install neo4j
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
25
715e438 @andreasronge released as 0.0.3. Updated documentation
andreasronge authored
26 To install from the source:
27 * Press the download button at http://github.com/andreasronge/neo4j/tree/master
28 * From command line type: ''rake gem:install''
29
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
30 JRuby version 1.1.4 does not work with Neo4j.rb because of a bug (JRUBY-2959).
31 This bug will be solved in JRuby 1.1.5. JRuby 1.1.3 does work.
32
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
33 == Two Minute Tutorial
34
35 class Person
36 include Neo4j::Node
37
049f162 @andreasronge replace relations with has and belongs_to, continued to impl. lucene ind...
andreasronge authored
38 # define Neo4j properties
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
39 properties :name, age
40
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
41 # define an one way relationship to any other Neo4j::Node
cd7889e @andreasronge impl has_n and has_one, see order_spec. Still many broken rspecs
andreasronge authored
42 has_n :friends
049f162 @andreasronge replace relations with has and belongs_to, continued to impl. lucene ind...
andreasronge authored
43
44 index 'name' # adds a lucene index on the name
45 index 'age'
46 index 'friends.age' # index each friend age as well
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
47 end
48
49 The example above specifies how to map a Neo node to a ruby Person instance.
50 All neo properties have to be declared (unless you include the DynamicAccessor mixin).
51 Relations between nodes can be specified by using the relations
52
53 Before using neo it has to be started
54
55 Neo4j::Neo.instance.start
56
57 Creating a Person node instance
58
59 person = Person.new
60
61 Setting a property:
62
63 person.name = 'kalle'
64 person.age = 23
65
66 If a transaction is not specified then the operation will automatically be wrapped in
67 a transaction.
68
049f162 @andreasronge replace relations with has and belongs_to, continued to impl. lucene ind...
andreasronge authored
69 Example of quering using lucene:
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
70
049f162 @andreasronge replace relations with has and belongs_to, continued to impl. lucene ind...
andreasronge authored
71 Person.find (:name => 'kalle')
72 Person.find ('friend.age' => 30) # find people who has a friend of age 30
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
73
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
74 or DSL, example finding person with name kalle or with age between 20 and 30:
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
75
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
76 Person.find ((name == 'kalle') | (age == 20..30)) # => [ person ]
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
77
78 Adding a relationship between two nodes:
79
80 person2 = Person.new
81 person.friends << person2
82
83 Traversing relationships
84
85 person.friends.each {|n| ... }
86
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
87 Traversing using a filter
88
89 person.friends{ age == 23 }.each {|n| ...}
90
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
91 Deleting a relationship
92
93 person.relations[person2].delete
94
95 Deleting a node (and all its relationships)
96
97 person.delete
98
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
99 Specifying relationships:
2a6f0a9 @andreasronge order rspecs now works. It tests indexing and quering of node relationsh...
andreasronge authored
100
cd7889e @andreasronge impl has_n and has_one, see order_spec. Still many broken rspecs
andreasronge authored
101 class Role
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
102 include Neo4j::Relation
cd7889e @andreasronge impl has_n and has_one, see order_spec. Still many broken rspecs
andreasronge authored
103 properties :name
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
104 end
cd7889e @andreasronge impl has_n and has_one, see order_spec. Still many broken rspecs
andreasronge authored
105
106 class Actor
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
107 include Neo4j::Node
cd7889e @andreasronge impl has_n and has_one, see order_spec. Still many broken rspecs
andreasronge authored
108 has_n(:acted_in).to(Movie).relation(Role)
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
109 end
110
cd7889e @andreasronge impl has_n and has_one, see order_spec. Still many broken rspecs
andreasronge authored
111 class Movie
112 include Neo4j::Node
113 properties :title
114 properties :year
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
115
116 # defines a method for traversing incoming acted_in relationships from Actor
117 has_n(:actors).from(Actor, :acted_in)
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
118 end
119
120
121 Notice that relationships also can have properties.
122 Creating a new Customer Order relationship can be done like this
123
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
124 keanu_reeves = Actor.new
125 matrix = Movie.new
126 keanu_reeves.acted_in << matrix
127
128 or you can also specify this relationship on the incoming node
129
130 keanu_reeves = Actor.new
131 matrix = Movie.new
132 matrix.actors << keanu_reeves
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
133
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
134 Example of accessing the Role between an Actor and a Movie
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
135
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
136 keanu_reeves = Actor.new
137 matrix = Movie.new
138 role = keanu_reeves.acted_in.new(matrix)
139 role.name = 'neo'
140
141 or
142 keanu_reeves = Actor.new
143 matrix = Movie.new
144 keanu_reeves.acted_in << matrix
145 keanu_reeves.acted_in
146 keanu_reeves.relations.outgoing(:acted_in)[matrix].name = 'neo'
6884854 @andreasronge Added support for mapping a ruby class to a neo relationship and setting...
andreasronge authored
147
9f6fdc6 @andreasronge Refactor properties method - split it into two: properties and index. St...
andreasronge authored
148
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
149 == The Lucene Module
150
4ccfae7 @andreasronge try to get a very simple gemspec to work
andreasronge authored
151 You can use this module without using the Neo4j module.
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
152
153 Example of how to write a document and find it:
f4f5752 @andreasronge updated README.rdoc
andreasronge authored
154 (a document is like a record or row in a relation database).
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
155
156 require 'lucene'
157
158 include Lucene
159
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
160 index = Index.new('var/myindex') # store the index at dir: var/myindex
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
161
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
162 # add one document (a document is like a record or row in a relation database)
163 index << {:id=>'1', :name=>'foo'}
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
164
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
165 # write to the index file
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
166 index.commit
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
167
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
168 # find a document with name foo
169 # hits is a ruby Enumeration of documents
21e45e7 @andreasronge Added support for filtering a graph traversal, Example person.friends{ n...
andreasronge authored
170 docs = index.find{name == 'foo'}
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
171
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
172 # show the id of the first document (document 0) found
173 # (the document contains all stored fields - see below)
21e45e7 @andreasronge Added support for filtering a graph traversal, Example person.friends{ n...
andreasronge authored
174 docs[0][:id] # => '1'
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
175
1c973d9 @andreasronge fixed several bugs regarding the lucene and neo transaction synchronizat...
andreasronge authored
176 Notice that you have to call the commit method in order to update the index on the disk.
177 By performing several update and delete operations before a commit will be much
178 faster then performing commit after each operation.
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
179
3e7df9d @andreasronge added support for indexing several values with the same key. This is nee...
andreasronge authored
180 === Indexing several values with the same key
181
182 Let say a person can have several phone numbers. How do we index that ?
183
184 index << {:id=>'1', :name=>'adam', :phone => ['987-654', '1234-5678']}
185
186
e477cf3 @andreasronge fixed some lucene bugs, update docs
andreasronge authored
187 === Id field
188
189 All Documents must have one id field. If one is not specified it is :id of type String.
190 A different id can be specified in the second parameter in the Index constructor.
191
192 Index.new('some/path/to/the/index', :my_id)
193
194 To change the type of the my_id from String to a different type see below.
195
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
196 === Conversion of types
197
e477cf3 @andreasronge fixed some lucene bugs, update docs
andreasronge authored
198 Lucene.rb can handle type conversion for you. (The java lucene library stores all
199 the fields as Strings)
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
200 For example if you want the id field to be a fixnum
201
202 require 'lucene'
203 include Lucene
204
205 index = Index.new('var/myindex') # store the index at dir: var/myindex
206 index.field_infos[:id][:type] = Fixnum
207
208 index << {:id=>1, :name=>'foo'} # notice 1 is not a string now
209
210 index.commit
211
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
212 # find that document, hits is a ruby Enumeration of documents
213 hits = index.find(:name => 'foo')
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
214
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
215 # show the id of the first document (document 0) found
216 # (the document contains all stored fields - see below)
217 doc[0][:id] # => 1
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
218
f4f5752 @andreasronge updated README.rdoc
andreasronge authored
219 If the field_info type parameter is not set then it has a default value of String.
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
220
221 === Storage of fields
222 By default only the id field will be stored.
223 That means that in the example above the :name field will not be included in the document.
224
225 Example
226 doc = index.find('name' => 'foo')
227 doc[:id] # => 1
228 doc[:name] # => nil
229
230 Use the field info :store=true if you want a field to be stored in the index
231 (otherwise it will only be searchable).
232
233 Example
234
235 require 'lucene'
236 include Lucene
237
238 index = Index.new('var/myindex') # store the index at dir: var/myindex
239 index.field_infos[:id][:type] = Fixnum
240 index.field_infos[:name][:store] = true # store this field
241
242 index << {:id=>1, :name=>'foo'} # notice 1 is not a string now
243
244 index.commit
245
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
246 # find that document, hits is a ruby Enumeration of documents
247 hits = index.find('name' => 'foo')
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
248
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
249 # let say hits only contains one document so we can use doc[0] for that one
250 # that document contains all stored fields (see below)
251 doc[0][:id] # => 1
252 doc[0][:name] # => 'foo'
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
253
f4f5752 @andreasronge updated README.rdoc
andreasronge authored
254 === Setting field infos
255
256 As shown above you can set field infos like this
257
258 index.field_infos[:id][:type] = Fixnum
259
260 Or you can set several properties like this:
261
262 index.field_infos[:id] = {:type => Fixnum, :store => true}
263
264
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
265 === Simple Queries
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
266
267 Lucene.rb support search in several fields:
268 Example
269
270 # finds all document having both name 'foo' and age 42
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
271 hits = index.find('name' => 'foo', :age=>42)
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
272
273 Range queries
274
275 # finds all document having both name 'foo' and age between 3 and 30
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
276 hits = index.find('name' => 'foo', :age=>3..30)
277
278 === Advanced Queries (DSL)
279
280 The queries above can also be written in a lucene.rb DSL:
281
282 hits = index.find { (name == 'andreas') & (foo == 'bar')}
283
5bcdd05 @andreasronge implemented OR DSL queries, example index.find {(name==andreas) | (age =...
andreasronge authored
284 Expression with OR (|) is supported, example
0fd1e72 @andreasronge impl Lucene Query DSL, some simple expression now works, updated RDoc an...
andreasronge authored
285
5bcdd05 @andreasronge implemented OR DSL queries, example index.find {(name==andreas) | (age =...
andreasronge authored
286 # find all documents with name 'andreas' or age between 30 and 40
287 hits = index.find { (name == 'andreas') | (age == 30..40)}
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
288
da1a6c9 @andreasronge major refactoring, made Lucene stuff thread safe, I hope
andreasronge authored
289 === Thread-safety
290
291 The Lucene::Index is thread safe.
292 It guarantees that an index is not updated from two thread at the same time.
293
294
295 === Lucene Transactions
296
f4f5752 @andreasronge updated README.rdoc
andreasronge authored
297 Use the Lucene::Transaction in order to do atomic commits.
298 By using a transaction you do not need to call the Index.commit method.
da1a6c9 @andreasronge major refactoring, made Lucene stuff thread safe, I hope
andreasronge authored
299
300 Example:
301
302 Transaction.run do |t|
303 index = Index.new('var/index/foo')
b836b1f @andreasronge fixed some lucene.rb bugs, updated README.rdoc
andreasronge authored
304 index << { id=>42, :name=>'andreas'}
da1a6c9 @andreasronge major refactoring, made Lucene stuff thread safe, I hope
andreasronge authored
305 t.failure # rollback
306 end
307
308 result = index.find('name' => 'andreas')
309 result.size.should == 0
310
4ccfae7 @andreasronge try to get a very simple gemspec to work
andreasronge authored
311 You can find which documents are uncommited by using the uncommited index property.
f4f5752 @andreasronge updated README.rdoc
andreasronge authored
312
4ccfae7 @andreasronge try to get a very simple gemspec to work
andreasronge authored
313 Example
314
315 index = Index.new('var/index/foo')
316 index.uncommited #=> [document1, document2]
317
318 Notice that even if it looks like a new Index instance object was created the index.uncommited
319 may return an not empty array. This is because Index.new is a singleton - a new instance object is not created.
320
79529ee @andreasronge major refactoring of lucene, put it in a new module 'Lucene', added RSpe...
andreasronge authored
321 == The Neo4j Module
322
77981c2 @andreasronge Continue to impl graph DSL (http://gist.github.com/5801). Updated README...
andreasronge authored
323 === Start and Stop of the Neo Database
324
325 In order to use neo it has to be started first.
326
327 Neo4j::Neo.instance.start
328
329 To stop the neo database:
330
331 Neo4j::Neo.instance.stop
332
333
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
334 === Neo4j::Node
5706e66 added more docs
andreasr authored
335
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
336 Neo4j::Node is a mixin that lets instances to be stored as a node in the neo node space on disk.
8a0d2d8 better docs
andreasr authored
337 A node can have properties and relationships to other nodes.
338
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
339 Example of how declare a class that has this behaviour:
5706e66 added more docs
andreasr authored
340
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
341 class MyNode
d94c3d0 @andreasronge added lucene test, fixed rdoc
andreasronge authored
342 include Neo4j::Node
4bf2f46 @andreasronge added some more specs
andreasronge authored
343 end
5706e66 added more docs
andreasr authored
344
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
345
8a0d2d8 better docs
andreasr authored
346 === Create a Node
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
347
348 If a block is provided then the creation of the instance will be performed in an
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
349 transaction, see below for more information on transactions.
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
350
351 node = MyNode.new { }
352
39632b2 @andreasronge implemented delete method on Nodes, updated RDoc
andreasronge authored
353 === Delete a Node
354
355 The Neo4j::Node mixin defines a delete method that will delete the node and all its relationships.
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
356
39632b2 @andreasronge implemented delete method on Nodes, updated RDoc
andreasronge authored
357 Example:
358
359 node = MyNode.new
360 node.delete
361
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
362 The node in the example above will be removed from the neo database on the filesystem and the lucene index
39632b2 @andreasronge implemented delete method on Nodes, updated RDoc
andreasronge authored
363
8a0d2d8 better docs
andreasr authored
364 === Node Properties
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
365
4bf2f46 @andreasronge added some more specs
andreasronge authored
366 In order to use properties they have to be declared first
367
368 class MyNode
369 include Neo4j::Node
370 properties :foo, :bar
371 end
372
373 These properties (foo and bar) will be stored in the Neo database.
374 You can set those properties:
5706e66 added more docs
andreasr authored
375
5fe54df @andreasronge fixed RDoc
andreasronge authored
376 # create a node with two properties in one transaction
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
377 node = MyNode.new { |n|
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
378 n.foo = 123
379 n.bar = 3.14
5706e66 added more docs
andreasr authored
380 }
381
382 # access those properties
383 puts node.foo
384
385
5fe54df @andreasronge fixed RDoc
andreasronge authored
386 You can also set a property like this:
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
387
388 f = SomeNode.new
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
389 f.foo = 123
019f9d0 @andreasronge store Transaction in Thread.current[:transaction], only one transaction ...
andreasronge authored
390
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
391 Neo4j.rb supports properties to by of type String, Fixnum, Float and Boolean.
5706e66 added more docs
andreasr authored
392
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
393
394 === Relationship has_n
5706e66 added more docs
andreasr authored
395
77981c2 @andreasronge Continue to impl graph DSL (http://gist.github.com/5801). Updated README...
andreasronge authored
396 Neo relationships are none symmetrical. That means that if A has a relation to B
397 then it may not be true that B has a relation to A.
398
39632b2 @andreasronge implemented delete method on Nodes, updated RDoc
andreasronge authored
399 Relationships has to be declared by using the 'relations' class method.
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
400 For example, let say that Person can have a relationship to other nodes with the type 'friends':
5706e66 added more docs
andreasr authored
401
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
402 class Person
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
403 include Neo::Node
715e438 @andreasronge released as 0.0.3. Updated documentation
andreasronge authored
404 has_n :knows # will generate a knows method for outgoing relationships
405 has_n(:known_by).from(:knows) # will generate a known_by method for incomming knows relationship
5706e66 added more docs
andreasr authored
406 end
407
39632b2 @andreasronge implemented delete method on Nodes, updated RDoc
andreasronge authored
408 Example how to add a relation to another node:
5706e66 added more docs
andreasr authored
409
715e438 @andreasronge released as 0.0.3. Updated documentation
andreasronge authored
410 me = Person.new
411 neo = Person.new
412 me.knows << neo # me knows neo but neo does not know me
413
414 Notice that you can also add relationship on the incoming relationship
415 The following example is the same as the example above:
416
417 me = Person.new
418 neo = Person.new
419 neo.known_by << me # neo is known by me, that means that I know neo but neo does have to know me
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
420
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
421 === Relationship has_one
422
423 Example of has_one: A person can have at most one Address
424
425 class Person
426 include Neo4j::Node
427 has_one(:address).to(Address)
428 end
429
430 class Address
431 include Neo4j::Node
432 properties :city, :road
433 has_n(:people).from(Person, :address)
434 end
435
436 In the example above we have Neo4j.rb will generate the following methods
7a1caf6 @andreasronge using neo-1.0-b7. had to do some minor changes to get all rspecs working...
andreasronge authored
437 * in Person, the method ''address='' and ''address''
438 * in Address, the traversal method ''people'' for traversing incomming relationships from the Person node.
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
439
440 Example of usage
441
442 p = Person.new
443 p.address = Address.new
444 p.address.city = 'malmoe'
445
446
447 Or from the incoming ''address'' relationship
448
449 a = Address.new {|n| n.city = 'malmoe'}
450 a.people << Person.new
451
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
452
5be9ad2 @andreasronge can now set properties on relationships
andreasronge authored
453 === Properties on a relationship
454
455 A relationship can have properties just like a node.
456
457 Example:
458
459 p1 = Person.new
460 p2 = Person.new
461
462 relation = p1.friends.new(p2)
463
464 # set a property 'since' on this relationship bewteen p1 and p2
465 relation.since = 1992
466
cb541b5 @andreasronge Updated README. Traversal and creating relationships now work both for i...
andreasronge authored
467 If a Relationship class has not been specified for a relationship then any properties
468 can be set on the relationship. It has a default relationship class: Neo4j::DynamicRelation
469
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
470 === Traversing relationships:
5706e66 added more docs
andreasr authored
471
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
472 Each type of relationship has a method that returns an Enumerable object that enables you
473 to traverse that type of relationship.
5706e66 added more docs
andreasr authored
474
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
475 For example the Person example above declares one relationship of type friends.
476 You can traverse all Person's friend by doing:
5706e66 added more docs
andreasr authored
477
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
478 f.friends.each { |n| puts n }
5706e66 added more docs
andreasr authored
479
cc30e2a @andreasronge Impl: Fires event when a relationship has been created. Updated README w...
andreasronge authored
480 === Filtering nodes in a relationship
481
482 If you want to find one node in a relationship you can use a filter.
483 Example, let say we want to find a friend with name 'andreas'
484
485 n1 = Person.new
486 n2 = Person.new {|n| n.name = 'andreas'}
487 n3 = Person.new
0a52ef1 @andreasronge Updated README
andreasronge authored
488 n1.friends << n2 << n3
cc30e2a @andreasronge Impl: Fires event when a relationship has been created. Updated README w...
andreasronge authored
489 n1.friends{ name == 'andreas' }.to_a # => [n2]
490
491 The block { name == 'andreas' } will be evaluated on each node in the relationship.
492 If the evaluation returns true the node will be included in the filter search result.
493
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
494 === Finding Relationships
495
496 Given we have the two nodes with a relationship between them:
497
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
498 n1 = Person.new
499 n2 = Person.new
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
500
501 n1.friends << n2
502
503 Then we can find all incoming and outgoing relationships like this:
504
505 n1.relations.to_a # => [#<Neo4j::Relation:0x134ae32]
506
5fe54df @andreasronge fixed RDoc
andreasronge authored
507 A Neo4j::Relation object represents a relationship between two nodes.
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
508
509 n1.relations[0].start_node # => n1
510 n1.relations[0].end_node # => n2
511
512 (TODO relationship can have properties just like a node can)
513
514 === Finding outgoing and incoming relationships
515
516 If we are only interested in all incoming nodes, we can do
517
518 n2.relations.incoming # => [#<Neo4j::Relation:0x134ae32]
519
5fe54df @andreasronge fixed RDoc
andreasronge authored
520 Or outgoing:
521
522 n1.relations.outgoing # => [#<Neo4j::Relation:0x134aea2]
523
baa8394 @andreasronge Added event for when a relationship is deleted, added [] operation on re...
andreasronge authored
524 To find a specific relationship use the [] operator:
525
526 n1.relations.outgoing[n2] = #<Neo4j::Relation:0x134aea2
527
528 Or which is better performance wise (since only friends relationships are being traversed):
529
530 n1.relations.outgoing(:friends)[n2] = #<Neo4j::Relation:0x134aea2
531
532 === Deleting a relationship
533
534 Use the Neo4j::Relation#delete method.
535 For example, to delete the relationship between n1 and n2 from the example above:
536
537 n1.relations.outgoing(:friends)[n2].delete
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
538
539 === Finding nodes in a relationship
540
5fe54df @andreasronge fixed RDoc
andreasronge authored
541 If you do not want those relationship object but instead want the nodes you can use the 'nodes' method
542 in the Neo4j::Relation object.
543
544 For example:
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
545
546 n2.relations.incoming.nodes # => [n1]
547
77981c2 @andreasronge Continue to impl graph DSL (http://gist.github.com/5801). Updated README...
andreasronge authored
548 === Finding outgoing/incoming nodes of a specific relationship type
0b0a127 @andreasronge implemented finding incoming/outgoing nodes of a specific type, started ...
andreasronge authored
549
550 Let say we want to find who has my phone number and who consider me as a friend
551
552 # who has my phone numbers
77981c2 @andreasronge Continue to impl graph DSL (http://gist.github.com/5801). Updated README...
andreasronge authored
553 me.relations.incoming(:phone_numbers).nodes # => people with my phone numbers
0b0a127 @andreasronge implemented finding incoming/outgoing nodes of a specific type, started ...
andreasronge authored
554
555 # who consider me as a friend
77981c2 @andreasronge Continue to impl graph DSL (http://gist.github.com/5801). Updated README...
andreasronge authored
556 me.relations.incoming(:friend).nodes # => people with a friend relationship to me
0b0a127 @andreasronge implemented finding incoming/outgoing nodes of a specific type, started ...
andreasronge authored
557
558 Remember that relationships are not symmetrical.
5706e66 added more docs
andreasr authored
559
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
560 === Transactions
561
562 All operations that work with the node space (even read operations) must be wrapped in a transaction.
563 Luckly neo4j.rb will automatically create a transaction for those operation that needs it if one is not already provided.
564
565 For example all get, set and find operations will start a new transaction if none is already not runnig (for that thread).
566
21e45e7 @andreasronge Added support for filtering a graph traversal, Example person.friends{ n...
andreasronge authored
567 If you want to perform a set of operation in a single transaction, use the Neo4j::Transaction.run method:
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
568
569 Example
570
ad7f747 @andreasronge removed meta nodes feature, added support for finding incoming/outgoing ...
andreasronge authored
571 Neo4j::Transaction.run {
572 node1.foo = "value"
573 node2.bar = "hi"
574 }
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
575
576
577 ==== Rollback
578
579 Neo4j support rollbacks on transaction. Example:
580 Example:
581
582 include 'neo4j'
583
584 node = MyNode.new
585
586 Neo4j::Transaction.run { |t|
587 node.foo = "hej"
588 # something failed so we signal for a failure
589 t.failure # will cause a rollback, node.foo will not be updated
590 }
591
592
593 You can also run it without a block, like this:
594
595 transaction = Neo4j::Transaction.new
596 transaction.start
597 # do something
598 transaction.finish
599
600 === Indexing
601
647c614 @andreasronge new release of neo4j, since github did not overwrite the old version 0.0...
andreasronge authored
602 If you want you can also declare properties to be indexed.
603 Use the properties class method, example:
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
604
605 class SomeNode
606 include Neo4j::Node
607 properties :foo, :bar
608 end
609
610
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
611 (TODO change name of properties to index ?)
3536220 @andreasronge fixed automatically create new transactions when needed, updated RDocs a...
andreasronge authored
612
b451e4c added find methods an all nodes, using lucene
andreasr authored
613 === Quering (using lucene)
614
4bf2f46 @andreasronge added some more specs
andreasronge authored
615 You can declare properties to be indexed by lucene by the index method:
b451e4c added find methods an all nodes, using lucene
andreasr authored
616
617 Example
618
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
619 class Person
b451e4c added find methods an all nodes, using lucene
andreasr authored
620 include Neo4j::Node
621 properties :name, :age
4bf2f46 @andreasronge added some more specs
andreasronge authored
622 index :name, :age
b451e4c added find methods an all nodes, using lucene
andreasr authored
623 end
624
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
625 node = Person.new
b451e4c added find methods an all nodes, using lucene
andreasr authored
626 node.name = 'foo'
627 node.age = 42
628
629
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
630 Person.find(:name => 'foo', :age => 42) # => [node]
5706e66 added more docs
andreasr authored
631
f4f5752 @andreasronge updated README.rdoc
andreasronge authored
632 The query parameter (like properties on a Neo4j::Node) can be of type String, Fixnum, Float, boolean or Range.
bd948f7 @andreasronge lucene dsl queries can now be used from Neo4j::Node
andreasronge authored
633 The query above can also be written in a lucene query DSL:
634
635 Person.find{(name =='foo') & (age => 42)} # => [node]
636
637 For more information see the lucene module above.
6887aa3 @andreasronge added documentation
andreasronge authored
638
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
639 === Indexing and Quering Relationships
640
cc30e2a @andreasronge Impl: Fires event when a relationship has been created. Updated README w...
andreasronge authored
641 The Neo4j::Node#index method can be used to index relationships to other classes.
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
642
643 Example, let say we have to classes, Customer and Orders:
644
645 class Customer
646 include Neo4j::Node
4bf2f46 @andreasronge added some more specs
andreasronge authored
647
648 properties :name
649
650 # specifies outgoing relationships to Order
651 has_n(:orders).to(Order)
652
653 # create an index on customer-->order#total_cost
654 index "orders.total_cost"
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
655 end
656
4bf2f46 @andreasronge added some more specs
andreasronge authored
657
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
658 class Order
659 include Neo4j::Node
660
4bf2f46 @andreasronge added some more specs
andreasronge authored
661 properties :total_cost
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
662
4bf2f46 @andreasronge added some more specs
andreasronge authored
663 # specifies one incoming relationship from Customer
664 has_one(:customer).from(Customer, :orders)
665
666 # create an index on the order<--customer#name relationship
667 index "customer.name"
668 end
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
669
4bf2f46 @andreasronge added some more specs
andreasronge authored
670 Notice that we can index both incoming and outgoing relationships.
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
671
672 Let's create a customer and one order for that customer
673
674 Neo4j::Transaction.run do
675 cust = Customer.new
676 order = Order.new
677 cust.name = "kalle"
4bf2f46 @andreasronge added some more specs
andreasronge authored
678 order.total_cost = "1000"
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
679
680 cust.orders << order
681 end
682
4bf2f46 @andreasronge added some more specs
andreasronge authored
683 Now we can find both Orders with a total cost between 500 and 2000 and Customers with name 'kalle' using lucene
684
685 Example:
686
687 customers = Customer.find('orders.total_cost' => 500..2000, 'name' => 'kalle')
688
689 Or also possible from the other way:
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
690
4bf2f46 @andreasronge added some more specs
andreasronge authored
691 orders = Order.find('total_cost' => 500..2000, 'customer.name' => 'kalle')
806daa5 @andreasronge Simple indexing and quering of relationships now works. Update README wi...
andreasronge authored
692
693
c08a13e added docs and more tests
andreasr authored
694 === Unmarshalling
695
696 The neo module will automatically unmarshalling nodes to the correct ruby class.
697 It does this by reading the classname property and loading that ruby class with that node.
698
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
699 class Person
cc536ec fixed ugly mixin workaround, more tests, refactoring NodeMixin->Node etc...
andreasr authored
700 include Neo::Node
701
c08a13e added docs and more tests
andreasr authored
702 def hello
703 end
704 end
705
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
706 f1 = Person.new {}
c08a13e added docs and more tests
andreasr authored
707
708 # load the class again
019f9d0 @andreasronge store Transaction in Thread.current[:transaction], only one transaction ...
andreasronge authored
709 f2 = Neo4j::Neo.instance.find_node(foo.neo_node_id)
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
710
711 # f2 will now be new instance of Person, but will be == f1
712 f1 == f2 # => true
cd1266e @andreasronge update TODO in RSpec README
andreasronge authored
713
7822b8a @andreasronge fixed: delete lucene index when the node is deleted, updated docs and sp...
andreasronge authored
714
21e45e7 @andreasronge Added support for filtering a graph traversal, Example person.friends{ n...
andreasronge authored
715
Something went wrong with that request. Please try again.