redcar 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +5 -0
- data/Rakefile +1 -2
- data/lib/redcar/installer.rb +2 -1
- data/lib/redcar.rb +2 -2
- data/plugins/project_search/vendor/lucene/CHANGELOG +147 -0
- data/plugins/project_search/vendor/lucene/CONTRIBUTORS +17 -0
- data/plugins/project_search/vendor/lucene/Gemfile +9 -0
- data/plugins/project_search/vendor/lucene/Gemfile.lock +33 -0
- data/plugins/project_search/vendor/lucene/LICENSE +19 -0
- data/plugins/project_search/vendor/lucene/README.rdoc +283 -0
- data/plugins/project_search/vendor/lucene/Rakefile +35 -0
- data/plugins/project_search/vendor/lucene/examples/active_model/serializers.rb +25 -0
- data/plugins/project_search/vendor/lucene/examples/active_model/validation.rb +26 -0
- data/plugins/project_search/vendor/lucene/examples/admin/Rakefile +4 -0
- data/plugins/project_search/vendor/lucene/examples/admin/admin.rb +29 -0
- data/plugins/project_search/vendor/lucene/examples/admin/public/jquery.js +4376 -0
- data/plugins/project_search/vendor/lucene/examples/admin/public/neo4j.css +153 -0
- data/plugins/project_search/vendor/lucene/examples/admin/public/neo_admin.js +18 -0
- data/plugins/project_search/vendor/lucene/examples/admin/spec/admin_spec.rb +26 -0
- data/plugins/project_search/vendor/lucene/examples/admin/views/index.erb +21 -0
- data/plugins/project_search/vendor/lucene/examples/filetree/README.rdoc +9 -0
- data/plugins/project_search/vendor/lucene/examples/filetree/app.rb +7 -0
- data/plugins/project_search/vendor/lucene/examples/filetree/batch.props +5 -0
- data/plugins/project_search/vendor/lucene/examples/filetree/features/step_definitions/add_steps.rb +121 -0
- data/plugins/project_search/vendor/lucene/examples/filetree/features/support/env.rb +30 -0
- data/plugins/project_search/vendor/lucene/examples/filetree/features/support/rspec_helper.rb +50 -0
- data/plugins/project_search/vendor/lucene/examples/filetree/features/treesizes.feature +19 -0
- data/plugins/project_search/vendor/lucene/examples/imdb/1_create_neo_db.rb +66 -0
- data/plugins/project_search/vendor/lucene/examples/imdb/2_index_db.rb +23 -0
- data/plugins/project_search/vendor/lucene/examples/imdb/README +12 -0
- data/plugins/project_search/vendor/lucene/examples/imdb/find_actors.rb +56 -0
- data/plugins/project_search/vendor/lucene/examples/imdb/install.sh +12 -0
- data/plugins/project_search/vendor/lucene/examples/imdb/model.rb +37 -0
- data/plugins/project_search/vendor/lucene/examples/railway/README +111 -0
- data/plugins/project_search/vendor/lucene/examples/railway/railnet-app.rb +31 -0
- data/plugins/project_search/vendor/lucene/examples/railway/railnet-data.rb +42 -0
- data/plugins/project_search/vendor/lucene/examples/rest/example.rb +41 -0
- data/plugins/project_search/vendor/lucene/examples/you_might_know/YouMightKnow.java +60 -0
- data/plugins/project_search/vendor/lucene/examples/you_might_know/all_simple_paths.rb +34 -0
- data/plugins/project_search/vendor/lucene/examples/you_might_know/nodes.rb +34 -0
- data/plugins/project_search/vendor/lucene/examples/you_might_know/you_might_know.rb +50 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/config.rb +145 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/document.rb +96 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/field_info.rb +144 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/hits.rb +54 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/index.rb +267 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/index_info.rb +146 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/index_searcher.rb +157 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/jars.rb +5 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/query_dsl.rb +135 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/transaction.rb +117 -0
- data/plugins/project_search/vendor/lucene/lib/lucene/version.rb +3 -0
- data/plugins/project_search/vendor/lucene/lib/lucene.rb +15 -0
- data/plugins/project_search/vendor/lucene/lucene.gemspec +23 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/document_spec.rb +32 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/field_info_spec.rb +70 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/index_info_spec.rb +76 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/index_spec.rb +643 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/query_dsl_spec.rb +142 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/sort_spec.rb +101 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/spec_helper.rb +10 -0
- data/plugins/project_search/vendor/lucene/spec/lucene/transaction_spec.rb +118 -0
- metadata +62 -4
@@ -0,0 +1,153 @@
|
|
1
|
+
body {
|
2
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
3
|
+
font-size: 90%;
|
4
|
+
margin: 0;
|
5
|
+
margin-left: 40px;
|
6
|
+
padding: 0;
|
7
|
+
background: white;
|
8
|
+
}
|
9
|
+
|
10
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
11
|
+
h1 { font-size: 150%; }
|
12
|
+
h2,h3,h4 { margin-top: 1em; }
|
13
|
+
|
14
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
15
|
+
a:hover { background: #039; color: #eef; }
|
16
|
+
|
17
|
+
/* Override the base stylesheets Anchor inside a table cell */
|
18
|
+
td > a {
|
19
|
+
background: transparent;
|
20
|
+
color: #039;
|
21
|
+
text-decoration: none;
|
22
|
+
}
|
23
|
+
|
24
|
+
/* and inside a section title */
|
25
|
+
.section-title > a {
|
26
|
+
background: transparent;
|
27
|
+
color: #eee;
|
28
|
+
text-decoration: none;
|
29
|
+
}
|
30
|
+
|
31
|
+
/* === Structural elements =================================== */
|
32
|
+
|
33
|
+
div#index {
|
34
|
+
margin: 0;
|
35
|
+
margin-left: -40px;
|
36
|
+
padding: 0;
|
37
|
+
font-size: 90%;
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
div#index a {
|
42
|
+
margin-left: 0.7em;
|
43
|
+
}
|
44
|
+
|
45
|
+
div#index .section-bar {
|
46
|
+
margin-left: 0px;
|
47
|
+
padding-left: 0.7em;
|
48
|
+
background: #ccc;
|
49
|
+
font-size: small;
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
div#classHeader, div#fileHeader {
|
54
|
+
width: auto;
|
55
|
+
color: white;
|
56
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
57
|
+
margin: 0;
|
58
|
+
margin-left: -40px;
|
59
|
+
border-bottom: 3px solid #006;
|
60
|
+
}
|
61
|
+
|
62
|
+
div#classHeader a, div#fileHeader a {
|
63
|
+
background: inherit;
|
64
|
+
color: white;
|
65
|
+
}
|
66
|
+
|
67
|
+
div#classHeader td, div#fileHeader td {
|
68
|
+
background: inherit;
|
69
|
+
color: white;
|
70
|
+
}
|
71
|
+
|
72
|
+
|
73
|
+
div#fileHeader {
|
74
|
+
background: #057;
|
75
|
+
}
|
76
|
+
|
77
|
+
div#classHeader {
|
78
|
+
background: #048;
|
79
|
+
}
|
80
|
+
|
81
|
+
|
82
|
+
.class-name-in-header {
|
83
|
+
font-size: 180%;
|
84
|
+
font-weight: bold;
|
85
|
+
}
|
86
|
+
|
87
|
+
|
88
|
+
div#bodyContent {
|
89
|
+
padding: 0 1.5em 0 1.5em;
|
90
|
+
}
|
91
|
+
|
92
|
+
div#description {
|
93
|
+
padding: 0.5em 1.5em;
|
94
|
+
background: #efefef;
|
95
|
+
border: 1px dotted #999;
|
96
|
+
}
|
97
|
+
|
98
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
99
|
+
color: #125;;
|
100
|
+
background: transparent;
|
101
|
+
}
|
102
|
+
|
103
|
+
div#validator-badges {
|
104
|
+
text-align: center;
|
105
|
+
}
|
106
|
+
div#validator-badges img { border: 0; }
|
107
|
+
|
108
|
+
div#copyright {
|
109
|
+
color: #333;
|
110
|
+
background: #efefef;
|
111
|
+
font: 0.75em sans-serif;
|
112
|
+
margin-top: 5em;
|
113
|
+
margin-bottom: 0;
|
114
|
+
padding: 0.5em 2em;
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
/* === Classes =================================== */
|
119
|
+
|
120
|
+
table.header-table {
|
121
|
+
color: white;
|
122
|
+
font-size: small;
|
123
|
+
}
|
124
|
+
|
125
|
+
.type-note {
|
126
|
+
font-size: small;
|
127
|
+
color: #DEDEDE;
|
128
|
+
}
|
129
|
+
|
130
|
+
.xxsection-bar {
|
131
|
+
background: #eee;
|
132
|
+
color: #333;
|
133
|
+
padding: 3px;
|
134
|
+
}
|
135
|
+
|
136
|
+
.section-bar {
|
137
|
+
color: #333;
|
138
|
+
border-bottom: 1px solid #999;
|
139
|
+
margin-left: -20px;
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
.section-title {
|
144
|
+
background: #79a;
|
145
|
+
color: #eee;
|
146
|
+
padding: 3px;
|
147
|
+
margin-top: 2em;
|
148
|
+
margin-left: -30px;
|
149
|
+
border: 1px solid #999;
|
150
|
+
}
|
151
|
+
|
152
|
+
.top-aligned-row { vertical-align: top }
|
153
|
+
.bottom-aligned-row { vertical-align: bottom }
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
$("a").click(function(event) {
|
3
|
+
data = $("#editor").val()
|
4
|
+
$.ajax({
|
5
|
+
type: "POST",
|
6
|
+
contentType: "text/plain",
|
7
|
+
url: "neo",
|
8
|
+
data: data,
|
9
|
+
cache: false,
|
10
|
+
success: function(res){
|
11
|
+
$("#statusbar").append(res);
|
12
|
+
return true;
|
13
|
+
}
|
14
|
+
});
|
15
|
+
event.preventDefault();
|
16
|
+
|
17
|
+
});
|
18
|
+
});
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require '../admin'
|
2
|
+
require 'spec'
|
3
|
+
|
4
|
+
require 'spec/interop/test'
|
5
|
+
require 'sinatra/test'
|
6
|
+
|
7
|
+
describe 'Neo4j Admin Suite' do
|
8
|
+
include Sinatra::Test
|
9
|
+
it "should serve the css" do
|
10
|
+
port = Sinatra::Application.port # we do not know it since we have not started it - mocked
|
11
|
+
# when
|
12
|
+
get "/neo4j.css"
|
13
|
+
|
14
|
+
# then
|
15
|
+
status.should_not == 404
|
16
|
+
end
|
17
|
+
it "should serve the index file" do
|
18
|
+
port = Sinatra::Application.port # we do not know it since we have not started it - mocked
|
19
|
+
# when
|
20
|
+
get "/"
|
21
|
+
|
22
|
+
# then
|
23
|
+
status.should_not == 404
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<script type="text/javascript" src="jquery.js"></script>
|
4
|
+
<script type="text/javascript" src="neo_admin.js"></script>
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<textarea id="editor" rows="10" cols="20">
|
8
|
+
class Person
|
9
|
+
include Neo4j::NodeMixin
|
10
|
+
# by includeing the following mixin we will expose this node as a RESTful resource
|
11
|
+
include RestMixin
|
12
|
+
property :name
|
13
|
+
has_n :friends
|
14
|
+
end
|
15
|
+
puts 'Hello World from Person'
|
16
|
+
</textarea>
|
17
|
+
<a href="">send</a>
|
18
|
+
<div id="statusbar" ></div>
|
19
|
+
|
20
|
+
</body>
|
21
|
+
</html>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
This is a small prototype for a typical graph use case: A file tree with folders and files. It even
|
2
|
+
demonstrates some of the speed tradeoff of using the JRuby-like traversing facilities and the underlying Java Traverser API directly
|
3
|
+
|
4
|
+
INSTALLATION
|
5
|
+
|
6
|
+
- install JRuby
|
7
|
+
|
8
|
+
gem install neo4j cucumber webrat sinatra
|
9
|
+
cucumber features/treesizes.feature
|
data/plugins/project_search/vendor/lucene/examples/filetree/features/step_definitions/add_steps.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../support")
|
2
|
+
require 'json'
|
3
|
+
require 'rspec_helper'
|
4
|
+
require 'neo4j'
|
5
|
+
|
6
|
+
Sinatra::Application.set :environment, :test
|
7
|
+
|
8
|
+
|
9
|
+
Before do
|
10
|
+
start
|
11
|
+
Neo4j.info
|
12
|
+
end
|
13
|
+
|
14
|
+
After do
|
15
|
+
stop
|
16
|
+
end
|
17
|
+
|
18
|
+
def createBatchSubtree(batch_neo, parent_props, currDepth, filesPerFolder, filesize, subfolders, maxDepth)
|
19
|
+
currDepth = currDepth + 1
|
20
|
+
if(currDepth>=maxDepth)
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
for k in 1..Integer(filesPerFolder)
|
25
|
+
props = java.util.HashMap.new
|
26
|
+
props.put('size',filesize)
|
27
|
+
props.put('name',"#{parent_props[:name]}/f#{k}")
|
28
|
+
#needed for JRuby compatibility
|
29
|
+
props.put('classname', Neo4j::Node.to_s)
|
30
|
+
file = batch_neo.createNode(props)
|
31
|
+
batch_neo.createRelationship( parent_props[:id], file, org.neo4j.graphdb.DynamicRelationshipType.withName('child'), nil)
|
32
|
+
end
|
33
|
+
for k in 1..Integer(subfolders)
|
34
|
+
props = java.util.HashMap.new
|
35
|
+
props.put('name',"#{parent_props[:name]}/d#{k}")
|
36
|
+
#needed for JRuby compatibility
|
37
|
+
props.put('classname', Neo4j::Node.to_s)
|
38
|
+
folder = batch_neo.createNode(props)
|
39
|
+
batch_neo.createRelationship(parent_props[:id], folder, org.neo4j.graphdb.DynamicRelationshipType.withName('child'), nil)
|
40
|
+
folder_props = {:name => props.get('name'),:id => folder}
|
41
|
+
createBatchSubtree(batch_neo, folder_props, currDepth, filesPerFolder, filesize, subfolders, maxDepth)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
When /^I create a filetree with (.*) files a (.*)kb and (\w+) subfolders in each folder, (\w+) times nested$/ do |filesPerFolder,filesize, nrSubfolders, timesNested|
|
47
|
+
size = Integer(filesize)
|
48
|
+
fileRoot = nil
|
49
|
+
Neo4j::Transaction.run do
|
50
|
+
fileRoot = Neo4j::Node.new
|
51
|
+
fileRoot[:name] = 'fileRoot'
|
52
|
+
Neo4j.ref_node.rels.outgoing(:files) << fileRoot
|
53
|
+
#create the owning user of the top folders
|
54
|
+
puts 'Created fileroot '
|
55
|
+
end
|
56
|
+
parent_props = {:name => fileRoot[:name], :id => fileRoot._java_node.getId()}
|
57
|
+
#stop Neo4j Embedded
|
58
|
+
stop
|
59
|
+
#start batch inserter to speed things up
|
60
|
+
startTime = Time.now
|
61
|
+
batch_neo = org.neo4j.kernel.impl.batchinsert.BatchInserterImpl.new('db/neo', org.neo4j.kernel.impl.batchinsert.BatchInserterImpl.loadProperties('batch.props'))
|
62
|
+
createBatchSubtree(batch_neo, parent_props, 0, Integer(filesPerFolder), Integer(filesize), Integer(nrSubfolders), Integer(timesNested))
|
63
|
+
#shut down the batchinserter
|
64
|
+
batch_neo.shutdown
|
65
|
+
puts "Insert time: " + (Time.now-startTime).to_s
|
66
|
+
#start Embedded Neo4j again
|
67
|
+
Neo4j.start
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
Then /^the total number of nodes in the db should be greater than (\w+)$/ do |totalFiles|
|
72
|
+
Neo4j::Transaction.run do
|
73
|
+
tot = Neo4j.number_of_nodes_in_use
|
74
|
+
puts "Total number of nodes in nodespace: #{tot}"
|
75
|
+
tot.should > Integer(totalFiles)
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def calcTotalSize(folder)
|
81
|
+
totSize = 0
|
82
|
+
folder.rels.outgoing(:child).nodes.each do |node|
|
83
|
+
if(node[:size] != nil)
|
84
|
+
totSize+=node[:size]
|
85
|
+
else #this is a folder
|
86
|
+
totSize+=calcTotalSize(node)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
return totSize
|
90
|
+
end
|
91
|
+
|
92
|
+
def calcSizeJava(node)
|
93
|
+
neoNode = node._java_node
|
94
|
+
size = 0
|
95
|
+
child = org.neo4j.graphdb.DynamicRelationshipType.withName 'child'
|
96
|
+
traverser = neoNode.traverse(org.neo4j.graphdb.Traverser::Order::DEPTH_FIRST,
|
97
|
+
org.neo4j.graphdb.StopEvaluator::END_OF_GRAPH,
|
98
|
+
org.neo4j.graphdb.ReturnableEvaluator::ALL, child, org.neo4j.graphdb.Direction::OUTGOING )
|
99
|
+
while traverser.hasNext()
|
100
|
+
node = traverser.next
|
101
|
+
if node.hasProperty('size')
|
102
|
+
size += node.getProperty('size')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
size
|
106
|
+
end
|
107
|
+
|
108
|
+
Then /^the total size of one top folder files should be (\w+) kb and response time less than (.*) s$/ do |totalSize, responseTime|
|
109
|
+
Neo4j::Transaction.run do
|
110
|
+
topFolder = Neo4j.ref_node.rels.outgoing(:files).nodes.first
|
111
|
+
startTime = Time.now
|
112
|
+
calcTotalSize(topFolder).should == Integer(totalSize)
|
113
|
+
rTime = Time.new-startTime
|
114
|
+
puts "time ruby: " + (rTime).to_s
|
115
|
+
startTime = Time.now
|
116
|
+
calcSizeJava(topFolder).should == Integer(totalSize)
|
117
|
+
rTime = Time.new-startTime
|
118
|
+
puts "time java: " + (rTime).to_s
|
119
|
+
rTime.should < Float(responseTime)
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# See http://wiki.github.com/aslakhellesoy/cucumber/sinatra
|
2
|
+
# for more details about Sinatra with Cucumber
|
3
|
+
|
4
|
+
gem 'rack-test'
|
5
|
+
gem 'sinatra'
|
6
|
+
|
7
|
+
app_file = File.join(File.dirname(__FILE__), *%w[.. .. app.rb])
|
8
|
+
require app_file
|
9
|
+
# Force the application name because polyglot breaks the auto-detection logic.
|
10
|
+
Sinatra::Application.app_file = app_file
|
11
|
+
|
12
|
+
require 'spec/expectations'
|
13
|
+
require 'rack/test'
|
14
|
+
require 'webrat'
|
15
|
+
|
16
|
+
Webrat.configure do |config|
|
17
|
+
config.mode = :rack
|
18
|
+
end
|
19
|
+
|
20
|
+
class MyWorld
|
21
|
+
include Rack::Test::Methods
|
22
|
+
include Webrat::Methods
|
23
|
+
include Webrat::Matchers
|
24
|
+
|
25
|
+
def app
|
26
|
+
Sinatra::Application
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
World{MyWorld.new}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# Helper methods for specs
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
require 'tmpdir'
|
7
|
+
|
8
|
+
# suppress all warnings
|
9
|
+
$NEO_LOGGER.level = Logger::ERROR
|
10
|
+
|
11
|
+
def delete_db
|
12
|
+
# delete db on filesystem
|
13
|
+
FileUtils.rm_rf Neo4j::Config[:storage_path] # NEO_STORAGE
|
14
|
+
FileUtils.rm_rf Lucene::Config[:storage_path] unless Lucene::Config[:storage_path].nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset_config
|
18
|
+
# reset configuration
|
19
|
+
Lucene::Config.delete_all
|
20
|
+
|
21
|
+
Neo4j::Config.delete_all
|
22
|
+
|
23
|
+
Neo4j::Config[:storage_path] = "db/neo"
|
24
|
+
Lucene::Config[:storage_path] = 'db/lucene'
|
25
|
+
Lucene::Config[:store_on_file] = true # otherwise it will keep the lucene index in memory !
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def start
|
30
|
+
puts "START"
|
31
|
+
# stop it - just in case
|
32
|
+
stop
|
33
|
+
|
34
|
+
delete_db
|
35
|
+
|
36
|
+
reset_config
|
37
|
+
Neo4j.start
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def stop
|
42
|
+
# make sure we finish all transactions
|
43
|
+
Neo4j::Transaction.finish if Neo4j::Transaction.running?
|
44
|
+
|
45
|
+
Neo4j.stop
|
46
|
+
|
47
|
+
#delete_db
|
48
|
+
|
49
|
+
reset_config
|
50
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Tree size calulations
|
2
|
+
In order to get some feeling for the file size performance
|
3
|
+
As a user
|
4
|
+
I want to test some traverse operations on Neo4j
|
5
|
+
|
6
|
+
# Scenario: Simple tests
|
7
|
+
# When I create a filetree with 2 files a 1kb and 1 subfolders in each folder, 3 times nested
|
8
|
+
# Then the total number of nodes in the db should be greater than 7
|
9
|
+
# Then the total size of one top folder files should be 4 kb and response time less than 0.015 s
|
10
|
+
|
11
|
+
Scenario: Bigger data sample
|
12
|
+
When I create a filetree with 400 files a 1kb and 50 subfolders in each folder, 3 times nested
|
13
|
+
Then the total number of nodes in the db should be greater than 20000
|
14
|
+
Then the total size of one top folder files should be 20400 kb and response time less than 0.5 s
|
15
|
+
|
16
|
+
# Scenario: Big data sample
|
17
|
+
# When I create a filetree with 3000 files a 1kb and 300 subfolders in each folder, 3 times nested
|
18
|
+
# Then the total number of nodes in the db should be greater than 20000
|
19
|
+
# Then the total size of one top folder files should be 20400 kb and response time less than 0.5 s
|
@@ -0,0 +1,66 @@
|
|
1
|
+
IMDB_FILE = 'data/test-actors.list'
|
2
|
+
|
3
|
+
Neo4j.migration 1, "Create DB by parsing IMDB file" do
|
4
|
+
up do
|
5
|
+
puts "Migration 1, processing #{IMDB_FILE} file ..."
|
6
|
+
Neo4j::Transaction.run do
|
7
|
+
movies = {}
|
8
|
+
current_actor = nil
|
9
|
+
actors = 0
|
10
|
+
no_films = 0
|
11
|
+
|
12
|
+
File.open(IMDB_FILE).each_line do |line|
|
13
|
+
next if line.strip.empty?
|
14
|
+
|
15
|
+
tab_items = line.split("\t")
|
16
|
+
|
17
|
+
unless tab_items.empty?
|
18
|
+
if !tab_items[0].empty?
|
19
|
+
current_actor = Actor.new
|
20
|
+
current_actor.name = tab_items.shift.strip
|
21
|
+
actors += 1
|
22
|
+
# puts "Parse new actor no. #{actors} '#{current_actor.name}'"
|
23
|
+
end
|
24
|
+
tab_items.shift
|
25
|
+
|
26
|
+
film = tab_items.shift.strip
|
27
|
+
|
28
|
+
# already created film ?
|
29
|
+
movie = movies[film]
|
30
|
+
if (movie.nil?)
|
31
|
+
movie = Movie.new
|
32
|
+
movie.title = film
|
33
|
+
movie.year = /\((\d+)(\/.)?\)/.match(film)[1]
|
34
|
+
movies[film] = movie
|
35
|
+
# puts "Created new film #{film}"
|
36
|
+
no_films += 1
|
37
|
+
end
|
38
|
+
|
39
|
+
role = tab_items.shift
|
40
|
+
roleNode = current_actor.acted_in.new(movie)
|
41
|
+
|
42
|
+
unless (role.nil?)
|
43
|
+
role.strip!
|
44
|
+
# remove []
|
45
|
+
role.slice!(0)
|
46
|
+
role.chop!
|
47
|
+
title, character = role.split('-')
|
48
|
+
roleNode.title = title.strip unless title.nil?
|
49
|
+
roleNode.character = character.strip unless character.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
#puts "Actor: '#{current_actor}' Film '#{film}' Year '#{year}' Title '#{title}' Character '#{character}'"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
puts "created #{actors} actors and #{no_films} films"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
down do
|
60
|
+
puts "deleting all movies and actors"
|
61
|
+
Neo4j::Transaction.run do
|
62
|
+
Actor.all.each {|a| a.del}
|
63
|
+
Movie.all.each {|m| m.del}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Neo4j.migration 2, "Index DB" do
|
2
|
+
up do
|
3
|
+
|
4
|
+
puts "Migration 2, Index DB on #{Lucene::Config[:storage_path]}"
|
5
|
+
|
6
|
+
Neo4j::Transaction.run do
|
7
|
+
puts "Creating lucene index ..."
|
8
|
+
Actor.index :name, :tokenized => true
|
9
|
+
start = Time.new
|
10
|
+
Actor.update_index
|
11
|
+
puts "Index speed #{Time.new - start} sec"
|
12
|
+
end
|
13
|
+
# only possible to access and query the index after the transaction commits
|
14
|
+
end
|
15
|
+
|
16
|
+
down do
|
17
|
+
puts "removing lucene index"
|
18
|
+
Actor.remove_index :name
|
19
|
+
# Actor.update_index # maybe nicer way of deleting indexes - hmm, does it work ?
|
20
|
+
require 'fileutils'
|
21
|
+
FileUtils.rm_rf Lucene::Config[:storage_path] # quick and dirty way of killing the lucene index
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Shows how to store and query a neo4j database
|
2
|
+
|
3
|
+
1. Download the database type: ./install.sh
|
4
|
+
2. Run the application: jruby find_actors.rb willis
|
5
|
+
|
6
|
+
The find_actors.rb uses migration which means that the first time the it is used it will take
|
7
|
+
a while to process the imdb file and create the index.
|
8
|
+
|
9
|
+
Notice that you can play around with migrations by require the 'find_actor' in JIRB and then for example
|
10
|
+
Neo4j.migrate! 1
|
11
|
+
which will delete the lucene index (migration number 2)
|
12
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../../lib")
|
2
|
+
require "rubygems"
|
3
|
+
require "neo4j"
|
4
|
+
|
5
|
+
# we have to configure these before the model is loaded
|
6
|
+
Lucene::Config[:store_on_file] = true
|
7
|
+
Lucene::Config[:storage_path] = "tmp/lucene"
|
8
|
+
|
9
|
+
|
10
|
+
require "model"
|
11
|
+
require "neo4j/extensions/reindexer"
|
12
|
+
|
13
|
+
|
14
|
+
# Keep lucene index on file system instead of in memory
|
15
|
+
|
16
|
+
|
17
|
+
# Load Migrations
|
18
|
+
# Create Database
|
19
|
+
require '1_create_neo_db'
|
20
|
+
|
21
|
+
# just for fun I have two migrations - first one for importing the database and second for indexing it.
|
22
|
+
require '2_index_db'
|
23
|
+
|
24
|
+
puts "Neo4j Version #{Neo4j::VERSION}"
|
25
|
+
|
26
|
+
def find_actor(name)
|
27
|
+
Neo4j::Transaction.run do
|
28
|
+
puts "Find all actors named #{name}"
|
29
|
+
result = Actor.find(:name => name)
|
30
|
+
|
31
|
+
puts "Found #{result.size} actors"
|
32
|
+
result.each {|x| puts "#{x.neo_id}\t#{x}"}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_movies(neo_id)
|
37
|
+
Neo4j::Transaction.run do
|
38
|
+
actor = Neo4j.load_node(neo_id)
|
39
|
+
puts "No actor found with neo id #{neo_id}" if actor.nil?
|
40
|
+
return if actor.nil?
|
41
|
+
|
42
|
+
puts "#{actor} acted in:"
|
43
|
+
actor.acted_in_rels.each {|r| puts "Movie #{r.end_node.title} title: #{r.title}"}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Neo4j.start
|
48
|
+
if (ARGV.size == 1)
|
49
|
+
find_actor(ARGV[0])
|
50
|
+
elsif ARGV.size == 2 && ARGV[0] == "-m"
|
51
|
+
find_movies(ARGV[1])
|
52
|
+
else
|
53
|
+
puts "Usage: jruby find_actors.rb [-m] <actor name|actor neo_id>\n\n -m \tfinds the movies for the given actor neo_id"
|
54
|
+
end
|
55
|
+
|
56
|
+
Neo4j.stop
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# In order to run this example the following files must be downloaded in unpacked
|
4
|
+
# in the data folder
|
5
|
+
|
6
|
+
mkdir data
|
7
|
+
cd data
|
8
|
+
wget https://trac.neo4j.org/export/2067/laboratory/users/andersn/imdb-app/src/test/data/test-actors.list.gz --no-check-certificate
|
9
|
+
wget https://trac.neo4j.org/export/2067/laboratory/users/andersn/imdb-app/src/test/data/test-movies.list.gz --no-check-certificate
|
10
|
+
gunzip test-actors.list.gz
|
11
|
+
gunzip test-movies.list.gz
|
12
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
class Movie; end
|
3
|
+
|
4
|
+
|
5
|
+
class Role
|
6
|
+
include Neo4j::RelationshipMixin
|
7
|
+
property :title, :character
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
"Role title #{self.title} character #{self.character}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Actor
|
15
|
+
include Neo4j::NodeMixin
|
16
|
+
property :name
|
17
|
+
has_n(:acted_in).to(Movie).relationship(Role)
|
18
|
+
index :name, :tokenized => true
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
"Actor #{self.name}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Movie
|
26
|
+
include Neo4j::NodeMixin
|
27
|
+
property :title
|
28
|
+
property :year
|
29
|
+
|
30
|
+
# defines a method for traversing incoming acted_in relationships from Actor
|
31
|
+
has_n(:actors).from(Actor, :acted_in)
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"Movie #{self.title}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|