daodalus 0.1.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/.gitignore +7 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +65 -0
- data/LICENCE.md +9 -0
- data/README.md +316 -0
- data/Rakefile +8 -0
- data/daodalus.gemspec +23 -0
- data/lib/daodalus.rb +29 -0
- data/lib/daodalus/connection.rb +19 -0
- data/lib/daodalus/dao.rb +41 -0
- data/lib/daodalus/dsl.rb +21 -0
- data/lib/daodalus/dsl/aggregation/group.rb +88 -0
- data/lib/daodalus/dsl/aggregation/limit.rb +23 -0
- data/lib/daodalus/dsl/aggregation/match.rb +35 -0
- data/lib/daodalus/dsl/aggregation/project.rb +79 -0
- data/lib/daodalus/dsl/aggregation/skip.rb +23 -0
- data/lib/daodalus/dsl/aggregation/sort.rb +29 -0
- data/lib/daodalus/dsl/aggregation/unwind.rb +23 -0
- data/lib/daodalus/dsl/aggregations.rb +44 -0
- data/lib/daodalus/dsl/clause.rb +19 -0
- data/lib/daodalus/dsl/matchers.rb +87 -0
- data/lib/daodalus/dsl/queries.rb +29 -0
- data/lib/daodalus/dsl/query.rb +46 -0
- data/lib/daodalus/dsl/select.rb +43 -0
- data/lib/daodalus/dsl/update.rb +86 -0
- data/lib/daodalus/dsl/updates.rb +71 -0
- data/lib/daodalus/dsl/where.rb +30 -0
- data/lib/daodalus/invalid_connection_error.rb +7 -0
- data/lib/daodalus/invalid_query_error.rb +4 -0
- data/spec/lib/daodalus/connection_spec.rb +22 -0
- data/spec/lib/daodalus/dao_spec.rb +34 -0
- data/spec/lib/daodalus/dsl/aggregation/group_spec.rb +92 -0
- data/spec/lib/daodalus/dsl/aggregation/limit_spec.rb +22 -0
- data/spec/lib/daodalus/dsl/aggregation/match_spec.rb +32 -0
- data/spec/lib/daodalus/dsl/aggregation/project_spec.rb +74 -0
- data/spec/lib/daodalus/dsl/aggregation/skip_spec.rb +22 -0
- data/spec/lib/daodalus/dsl/aggregation/sort_spec.rb +36 -0
- data/spec/lib/daodalus/dsl/aggregation/unwind_spec.rb +24 -0
- data/spec/lib/daodalus/dsl/clause_spec.rb +22 -0
- data/spec/lib/daodalus/dsl/query_spec.rb +35 -0
- data/spec/lib/daodalus/dsl/select_spec.rb +46 -0
- data/spec/lib/daodalus/dsl/update_spec.rb +113 -0
- data/spec/lib/daodalus/dsl/where_spec.rb +133 -0
- data/spec/lib/daodalus/dsl_spec.rb +12 -0
- data/spec/pointless_coverage_spec.rb +9 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/mongo_cleaner.rb +12 -0
- metadata +208 -0
data/lib/daodalus.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'optional'
|
3
|
+
|
4
|
+
require 'daodalus/connection'
|
5
|
+
require 'daodalus/invalid_connection_error'
|
6
|
+
require 'daodalus/invalid_query_error'
|
7
|
+
|
8
|
+
require 'daodalus/dsl/query'
|
9
|
+
require 'daodalus/dsl/clause'
|
10
|
+
require 'daodalus/dsl/matchers'
|
11
|
+
|
12
|
+
require 'daodalus/dsl/queries'
|
13
|
+
require 'daodalus/dsl/updates'
|
14
|
+
|
15
|
+
require 'daodalus/dsl/where'
|
16
|
+
require 'daodalus/dsl/select'
|
17
|
+
require 'daodalus/dsl/update'
|
18
|
+
|
19
|
+
require 'daodalus/dsl/aggregations'
|
20
|
+
require 'daodalus/dsl/aggregation/match'
|
21
|
+
require 'daodalus/dsl/aggregation/group'
|
22
|
+
require 'daodalus/dsl/aggregation/project'
|
23
|
+
require 'daodalus/dsl/aggregation/limit'
|
24
|
+
require 'daodalus/dsl/aggregation/skip'
|
25
|
+
require 'daodalus/dsl/aggregation/sort'
|
26
|
+
require 'daodalus/dsl/aggregation/unwind'
|
27
|
+
|
28
|
+
require 'daodalus/dsl'
|
29
|
+
require 'daodalus/dao'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Daodalus
|
2
|
+
|
3
|
+
module Connection
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def register(connection, name='default')
|
7
|
+
connections[name.to_s] = connection
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch(name='default')
|
11
|
+
connections.fetch(name.to_s) { raise InvalidConnectionError.new(name) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def connections
|
15
|
+
@connections ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/daodalus/dao.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Daodalus
|
4
|
+
class DAO
|
5
|
+
include DSL
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def initialize(db, collection, connection=:default)
|
9
|
+
@db = db
|
10
|
+
@collection = collection
|
11
|
+
@connection = connection
|
12
|
+
end
|
13
|
+
|
14
|
+
def coll
|
15
|
+
@coll ||= Daodalus::Connection.fetch(connection)[db.to_s][collection.to_s]
|
16
|
+
end
|
17
|
+
|
18
|
+
delegate [
|
19
|
+
:find,
|
20
|
+
:update,
|
21
|
+
:insert,
|
22
|
+
:save,
|
23
|
+
:remove,
|
24
|
+
:count,
|
25
|
+
:aggregate
|
26
|
+
] => :coll
|
27
|
+
|
28
|
+
def find_one(*args)
|
29
|
+
Option[coll.find_one(*args)]
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_and_modify(*args)
|
33
|
+
Option[coll.find_and_modify(*args)]
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :db, :collection, :connection
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
data/lib/daodalus/dsl.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregation
|
4
|
+
class Group
|
5
|
+
include Aggregations
|
6
|
+
|
7
|
+
def initialize(dao, aggregations, id, values)
|
8
|
+
@dao = dao
|
9
|
+
@aggregations = aggregations
|
10
|
+
@id = id
|
11
|
+
@values = values
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_aggregation
|
15
|
+
{ '$group' => values.merge('_id' => id) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def sum(field)
|
19
|
+
aliased '$sum' => field
|
20
|
+
end
|
21
|
+
alias_method :total, :sum
|
22
|
+
|
23
|
+
def add_to_set(field)
|
24
|
+
aliased '$addToSet' => field
|
25
|
+
end
|
26
|
+
alias_method :distinct, :add_to_set
|
27
|
+
|
28
|
+
def push(field)
|
29
|
+
aliased '$push' => field
|
30
|
+
end
|
31
|
+
alias_method :collect, :push
|
32
|
+
|
33
|
+
def first(field)
|
34
|
+
aliased '$first' => field
|
35
|
+
end
|
36
|
+
|
37
|
+
def last(field)
|
38
|
+
aliased '$last' => field
|
39
|
+
end
|
40
|
+
|
41
|
+
def max(field)
|
42
|
+
aliased '$max' => field
|
43
|
+
end
|
44
|
+
|
45
|
+
def min(field)
|
46
|
+
aliased '$min' => field
|
47
|
+
end
|
48
|
+
|
49
|
+
def avg(field)
|
50
|
+
aliased '$avg' => field
|
51
|
+
end
|
52
|
+
alias_method :average, :avg
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def id
|
57
|
+
case @id
|
58
|
+
when Symbol then @id.to_s
|
59
|
+
when Hash then @id.reduce({}) {|acc, (a,b)| acc.merge(a.to_s => b.to_s) }
|
60
|
+
else @id
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def aliased clause
|
65
|
+
Alias.new do |aka|
|
66
|
+
Group.new(dao, aggregations, id, values.merge(aka => clause))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
attr_reader :dao, :aggregations, :values
|
71
|
+
|
72
|
+
class Alias
|
73
|
+
def initialize(&block)
|
74
|
+
@block = block
|
75
|
+
end
|
76
|
+
|
77
|
+
def as(aka)
|
78
|
+
block.call(aka)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
attr_reader :block
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregation
|
4
|
+
class Limit
|
5
|
+
include Aggregations
|
6
|
+
|
7
|
+
def initialize(dao, aggregations, limit)
|
8
|
+
@dao = dao
|
9
|
+
@aggregations = aggregations
|
10
|
+
@limit = limit
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_aggregation
|
14
|
+
{ '$limit' => limit }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :dao, :aggregations, :limit
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregation
|
4
|
+
class Match
|
5
|
+
include Matchers
|
6
|
+
include Aggregations
|
7
|
+
|
8
|
+
def initialize(dao, aggregations, query, field)
|
9
|
+
@dao = dao
|
10
|
+
@aggregations = aggregations
|
11
|
+
@query = query
|
12
|
+
@field = field
|
13
|
+
end
|
14
|
+
|
15
|
+
alias_method :and, :match
|
16
|
+
|
17
|
+
def to_aggregation
|
18
|
+
{ '$match' => query.wheres }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def add_clause clause
|
24
|
+
Match.new(dao, aggregations, query.where(field.to_s => clause), field)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_logical_clause clause
|
28
|
+
Match.new(dao, aggregations, query.where(clause), field)
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :dao, :aggregations, :query, :field
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregation
|
4
|
+
class Project
|
5
|
+
include Aggregations
|
6
|
+
|
7
|
+
def initialize(dao, aggregations, projection = {}, keys)
|
8
|
+
@dao = dao
|
9
|
+
@aggregations = aggregations
|
10
|
+
@projection = projection
|
11
|
+
@keys = keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_aggregation
|
15
|
+
{ '$project' => { '_id' => 0 }.merge(projection) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def project(*keys)
|
19
|
+
Project.new(dao, aggregations, projection, keys)
|
20
|
+
end
|
21
|
+
alias_method :and, :project
|
22
|
+
|
23
|
+
def as(aka)
|
24
|
+
Project.new(dao, aggregations, @projection, [aka => keys.first])
|
25
|
+
end
|
26
|
+
|
27
|
+
def eq(*others)
|
28
|
+
Project.new(dao, aggregations, @projection, ['$eq' => keys + others])
|
29
|
+
end
|
30
|
+
|
31
|
+
def add(*others)
|
32
|
+
Project.new(dao, aggregations, @projection, ['$add' => keys + others])
|
33
|
+
end
|
34
|
+
alias_method :plus, :add
|
35
|
+
|
36
|
+
def divide(other)
|
37
|
+
Project.new(dao, aggregations, @projection, ['$divide' => keys + [other]])
|
38
|
+
end
|
39
|
+
alias_method :divided_by, :divide
|
40
|
+
|
41
|
+
def multiply(other)
|
42
|
+
Project.new(dao, aggregations, @projection, ['$multiply' => keys + [other]])
|
43
|
+
end
|
44
|
+
alias_method :multiplied_by, :multiply
|
45
|
+
|
46
|
+
def subtract(other)
|
47
|
+
Project.new(dao, aggregations, @projection, ['$subtract' => keys + [other]])
|
48
|
+
end
|
49
|
+
alias_method :minus, :subtract
|
50
|
+
|
51
|
+
def mod(other)
|
52
|
+
Project.new(dao, aggregations, @projection, ['$mod' => keys + [other]])
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def projection
|
58
|
+
keys.reduce(@projection) do |acc, k|
|
59
|
+
case k
|
60
|
+
when Hash then acc.merge(hashify k)
|
61
|
+
else acc.merge(k.to_s => 1)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def hashify(key)
|
69
|
+
case key
|
70
|
+
when Hash then key.reduce({}) { |acc, (k,v)| acc.merge(k => hashify(v)) }
|
71
|
+
when Project then hashify key.projection
|
72
|
+
else key
|
73
|
+
end
|
74
|
+
end
|
75
|
+
attr_reader :dao, :aggregations, :keys
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregation
|
4
|
+
class Skip
|
5
|
+
include Aggregations
|
6
|
+
|
7
|
+
def initialize(dao, aggregations, skip)
|
8
|
+
@dao = dao
|
9
|
+
@aggregations = aggregations
|
10
|
+
@skip = skip
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_aggregation
|
14
|
+
{ '$skip' => skip }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :dao, :aggregations, :skip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregation
|
4
|
+
class Sort
|
5
|
+
include Aggregations
|
6
|
+
|
7
|
+
def initialize(dao, aggregations, keys)
|
8
|
+
@dao = dao
|
9
|
+
@aggregations = aggregations
|
10
|
+
@keys = keys
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_aggregation
|
14
|
+
{ '$sort' => keys }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def keys
|
20
|
+
@keys.reduce({}) do |acc, (k,v)|
|
21
|
+
acc.merge(k => ([-1, :desc, 'desc'].include?(v) ? -1 : 1))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :dao, :aggregations
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregation
|
4
|
+
class Unwind
|
5
|
+
include Aggregations
|
6
|
+
|
7
|
+
def initialize(dao, aggregations, field)
|
8
|
+
@dao = dao
|
9
|
+
@aggregations = aggregations
|
10
|
+
@field = field
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_aggregation
|
14
|
+
{ '$unwind' => "$#{field}" }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :dao, :aggregations, :field
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Daodalus
|
2
|
+
module DSL
|
3
|
+
module Aggregations
|
4
|
+
|
5
|
+
def aggregate
|
6
|
+
dao.aggregate(pipeline)
|
7
|
+
end
|
8
|
+
|
9
|
+
def match(field=nil)
|
10
|
+
Aggregation::Match.new(dao, pipeline, Query.new, field)
|
11
|
+
end
|
12
|
+
|
13
|
+
def group(keys)
|
14
|
+
Aggregation::Group.new(dao, pipeline, keys, {})
|
15
|
+
end
|
16
|
+
alias_method :group_by, :group
|
17
|
+
|
18
|
+
def project(*keys)
|
19
|
+
Aggregation::Project.new(dao, pipeline, keys)
|
20
|
+
end
|
21
|
+
|
22
|
+
def limit(limit)
|
23
|
+
Aggregation::Limit.new(dao, pipeline, limit)
|
24
|
+
end
|
25
|
+
|
26
|
+
def skip(skip)
|
27
|
+
Aggregation::Skip.new(dao, pipeline, skip)
|
28
|
+
end
|
29
|
+
|
30
|
+
def sort(sort)
|
31
|
+
Aggregation::Sort.new(dao, pipeline, sort)
|
32
|
+
end
|
33
|
+
|
34
|
+
def unwind(field)
|
35
|
+
Aggregation::Unwind.new(dao, pipeline, field)
|
36
|
+
end
|
37
|
+
|
38
|
+
def pipeline
|
39
|
+
aggregations + [to_aggregation]
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|