mongo_ql 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 54ebbab82b00ce95966996491caf76cea95683f8f88be3676f15655c836ffa6b
4
+ data.tar.gz: 4e9bd70e840f6f2c118fcba06e8d086ceca67d42bfa8ecd82d3cf8412dd9191e
5
+ SHA512:
6
+ metadata.gz: 591efcb215b9769e6be3e4cdbf0d493a6c3800042fec75a649852afd0901b25916ad063516a3f46af05b9a44bdb62eb5cd719f754624d7b15135e85177e3e7d3
7
+ data.tar.gz: 586002d366b3d6f264ee8e6621297679febed34b869e6a9c94d4e9698d64a58a07d663b275d313682bef6d7ef16edf1187bd535503312e67acc53abdaea17264
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile*.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,173 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+ # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
4
+ # to ignore them, so only the ones explicitly set in this file are enabled.
5
+ DisabledByDefault: true
6
+ Exclude:
7
+ - 'bin/**/*'
8
+ - 'Rakefile'
9
+
10
+ # Security
11
+ Security:
12
+ Enabled: true
13
+
14
+ Security/YAMLLoad:
15
+ Enabled: false
16
+
17
+ # Prefer &&/|| over and/or.
18
+ Style/AndOr:
19
+ Enabled: true
20
+
21
+ # Do not use braces for hash literals when they are the last argument of a
22
+ # method call.
23
+ Style/BracesAroundHashParameters:
24
+ Enabled: true
25
+ EnforcedStyle: context_dependent
26
+
27
+ # Align `when` with `case`.
28
+ Layout/CaseIndentation:
29
+ Enabled: true
30
+
31
+ # Align comments with method definitions.
32
+ Layout/CommentIndentation:
33
+ Enabled: true
34
+
35
+ Layout/ElseAlignment:
36
+ Enabled: true
37
+
38
+ Layout/EmptyLineAfterMagicComment:
39
+ Enabled: false
40
+
41
+ # In a regular class definition, no empty lines around the body.
42
+ Layout/EmptyLinesAroundClassBody:
43
+ Enabled: true
44
+
45
+ # In a regular method definition, no empty lines around the body.
46
+ Layout/EmptyLinesAroundMethodBody:
47
+ Enabled: true
48
+
49
+ # In a regular module definition, no empty lines around the body.
50
+ Layout/EmptyLinesAroundModuleBody:
51
+ Enabled: false
52
+
53
+ Layout/IndentFirstArgument:
54
+ Enabled: true
55
+
56
+ # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
57
+ Style/HashSyntax:
58
+ Enabled: true
59
+
60
+ # Method definitions after `private` or `protected` isolated calls need one
61
+ # extra level of indentation.
62
+ Layout/IndentationConsistency:
63
+ Enabled: true
64
+ EnforcedStyle: indented_internal_methods
65
+
66
+ # Two spaces, no tabs (for indentation).
67
+ Layout/IndentationWidth:
68
+ Enabled: true
69
+
70
+ Layout/LeadingCommentSpace:
71
+ Enabled: true
72
+
73
+ Layout/SpaceAfterColon:
74
+ Enabled: true
75
+
76
+ Layout/SpaceAfterComma:
77
+ Enabled: true
78
+
79
+ Layout/SpaceAroundEqualsInParameterDefault:
80
+ Enabled: true
81
+
82
+ Layout/SpaceAroundKeyword:
83
+ Enabled: true
84
+
85
+ Layout/SpaceAroundOperators:
86
+ Enabled: true
87
+
88
+ Layout/SpaceBeforeComma:
89
+ Enabled: true
90
+
91
+ Layout/SpaceBeforeFirstArg:
92
+ Enabled: true
93
+
94
+ Style/DefWithParentheses:
95
+ Enabled: true
96
+
97
+ # Defining a method with parameters needs parentheses.
98
+ Style/MethodDefParentheses:
99
+ Enabled: true
100
+
101
+ Style/FrozenStringLiteralComment:
102
+ Enabled: true
103
+ EnforcedStyle: always
104
+ Exclude:
105
+ - 'actionview/test/**/*.builder'
106
+ - 'actionview/test/**/*.ruby'
107
+ - 'actionpack/test/**/*.builder'
108
+ - 'actionpack/test/**/*.ruby'
109
+ - 'activestorage/db/migrate/**/*.rb'
110
+ - 'db/migrate/**/*.rb'
111
+ - 'db/*.rb'
112
+
113
+ # Use `foo {}` not `foo{}`.
114
+ Layout/SpaceBeforeBlockBraces:
115
+ Enabled: true
116
+
117
+ # Use `foo { bar }` not `foo {bar}`.
118
+ Layout/SpaceInsideBlockBraces:
119
+ Enabled: true
120
+
121
+ # Use `{ a: 1 }` not `{a:1}`.
122
+ Layout/SpaceInsideHashLiteralBraces:
123
+ Enabled: false
124
+
125
+ Layout/SpaceInsideParens:
126
+ Enabled: true
127
+
128
+ # Check quotes usage according to lint rule below.
129
+ Style/StringLiterals:
130
+ Enabled: true
131
+ EnforcedStyle: double_quotes
132
+
133
+ # Detect hard tabs, no hard tabs.
134
+ Layout/Tab:
135
+ Enabled: true
136
+
137
+ # Blank lines should not have any spaces.
138
+ Layout/TrailingBlankLines:
139
+ Enabled: false
140
+
141
+ # No trailing whitespace.
142
+ Layout/TrailingWhitespace:
143
+ Enabled: true
144
+
145
+ # Use quotes for string literals when they are enough.
146
+ Style/UnneededPercentQ:
147
+ Enabled: true
148
+
149
+ Lint:
150
+ Enabled: true
151
+
152
+ Lint/UselessAccessModifier:
153
+ Enabled: false
154
+
155
+ Lint/UnusedMethodArgument:
156
+ Enabled: false
157
+
158
+ Style/RedundantReturn:
159
+ Enabled: true
160
+ AllowMultipleReturnValues: true
161
+
162
+ Style/Semicolon:
163
+ Enabled: true
164
+ AllowAsExpressionSeparator: true
165
+
166
+ Naming/AccessorMethodName:
167
+ Enabled: true
168
+
169
+ Naming/ConstantName:
170
+ Enabled: true
171
+
172
+ Naming/FileName:
173
+ Enabled: true
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 KUBERCLOUD SOLUTIONS INC.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # mongo_ql
data/Untitled-1 ADDED
@@ -0,0 +1,4 @@
1
+ include MongoQL
2
+ define_singleton_method(:method_missing) do |m, *args, &block|
3
+ MongoQL::Expression::FieldNode.new(m)
4
+ end
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "./lib/mongo_ql"
5
+
6
+ require "irb"
7
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
data/design_specs.md ADDED
@@ -0,0 +1,80 @@
1
+
2
+ # Query DSL
3
+ ```ruby
4
+ Order.where { tax != 0 }
5
+ #=> Order.where(tax: { "$ne": 0 })
6
+ Order.where { total >= 100 }
7
+ #=> Order.where(total: { "$gte": 100 })
8
+ Order.where { (total >= 100) & (total_tax < 15) }
9
+ #=> Order.where({ "$and": [{ total: { "$gte": 100 }}, { total_tax: { "$lt": 15 }}]})
10
+ Order.where { tax > (shipping / 2) }
11
+ #=> Order.where(tax: { "$gt": { "$divide": [ "$shipping", 2]}})
12
+ Order.where { total >= If(currency == "CAD", 100, 80) }
13
+ #=> Order.where(total: { "$cond": { if: { "$eq": ["$currency", "CAD"]}, then: 100, else: 80 }})
14
+ ```
15
+
16
+ # Aggregation Pipeline DSL
17
+ ```ruby
18
+ Order.all.mongo_ql do
19
+ join Customer,
20
+ :customer_id => _id,
21
+ :as => customers
22
+
23
+ join Shipping, :as => shippings do
24
+ match order_id == doc._id,
25
+ status == :shipped
26
+ end
27
+
28
+ match province == "ON"
29
+
30
+ project :_id,
31
+ :total,
32
+ :customer => customers.name,
33
+ :tax => total * tax_rate
34
+
35
+ group customer,
36
+ :total => total.sum,
37
+ :total_tax => tax.sum * 5
38
+ end
39
+
40
+ # The above aggregation is equivalent to the following mognodb pipeline
41
+ Order.collection.pipeline([
42
+ { "$lookup": {
43
+ from: "customers",
44
+ localField: "$customer_id",
45
+ foreignField: "$_id",
46
+ as: "customers"
47
+ }},
48
+ { "$unwind": {
49
+ path: "customers"
50
+ }},
51
+ { "$lookup": {
52
+ from: "shippings",
53
+ as: "shippings",
54
+ let: { doc_id: "$_id" },
55
+ pipeline: [{
56
+ "$match": {
57
+ order_id: { "$eq": "$$dock_id" },
58
+ status: :shipped
59
+ }
60
+ }]
61
+ }},
62
+ { "$unwind": {
63
+ path: "customers"
64
+ }},
65
+ { "$match": {
66
+ province: { "$eq": "ON" }
67
+ }},
68
+ { "$project": {
69
+ _id: 1,
70
+ total: 1,
71
+ customer: "$customers.name",
72
+ tax: { "$multiply": ["$total", "$tax_rate"] }
73
+ }},
74
+ { "$group": {
75
+ _id: "$customer",
76
+ total: { "$sum": "$total" },
77
+ total_tax: { "$multiply": [{ "$sum": "$tax" }, 5] }
78
+ }}
79
+ ])
80
+ ```
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ module BinaryOperators
5
+ BINARY_OPS = {
6
+ "+": "$add",
7
+ "-": "$subtract",
8
+ "*": "$multiply",
9
+ "/": "$divide",
10
+ ">": "$gt",
11
+ "<": "$lt",
12
+ ">=": "$gte",
13
+ "<=": "$lte",
14
+ "!=": "$ne",
15
+ "==": "$eq",
16
+ "&": "$and",
17
+ "|": "$or",
18
+ "%": "$mod",
19
+ "**": "$pow"
20
+ }.freeze
21
+
22
+ BINARY_OPS.keys.each do |op|
23
+ class_eval <<~RUBY
24
+ def #{op}(right_node)
25
+ Expression::Binary.new(BINARY_OPS[__method__], self, right_node)
26
+ end
27
+ RUBY
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ module CollectionOperators
5
+ AGGREGATE_OPS = {
6
+ "max": "$max",
7
+ "min": "$min",
8
+ "first": "$first",
9
+ "last": "$last",
10
+ "sum": "$sum",
11
+ "avg": "$avg",
12
+ "size": "$size",
13
+ "push": "$push"
14
+ }.freeze
15
+
16
+ AGGREGATE_OPS.keys.each do |op|
17
+ class_eval <<~RUBY
18
+ def #{op}
19
+ Expression::MethodCall.new(AGGREGATE_OPS[__method__], self)
20
+ end
21
+ RUBY
22
+ end
23
+
24
+ def filter(&block)
25
+ Expression::MethodCall.new "$filter", self, ast_template: -> (target, **_args) {
26
+ {
27
+ "input" => target,
28
+ "as" => "item",
29
+ "cond" => block.call(Expression::FieldNode.new("$item")).to_ast
30
+ }
31
+ }
32
+ end
33
+
34
+ def map(&block)
35
+ Expression::MethodCall.new "$map", self, ast_template: -> (target, **_args) {
36
+ {
37
+ "input" => target,
38
+ "as" => "item",
39
+ "in" => block.call(Expression::FieldNode.new("$item")).to_ast
40
+ }
41
+ }
42
+ end
43
+
44
+ def reduce(initial_value, &block)
45
+ Expression::MethodCall.new "$reduce", self, ast_template: -> (target, **_args) {
46
+ {
47
+ "input" => target,
48
+ "initialValue" => to_expression(initial_value).to_ast,
49
+ "in" => to_expression(block.call(Expression::FieldNode.new("$value"), Expression::FieldNode.new("$this"))).to_ast
50
+ }
51
+ }
52
+ end
53
+
54
+ def contains(ele)
55
+ Expression::MethodCall.new "$in", self, ast_template: -> (target, **_args) {
56
+ [to_expression(ele).to_ast, target]
57
+ }
58
+ end
59
+ alias_method :includes, :contains
60
+ alias_method :include, :contains
61
+ alias_method :include?, :contains
62
+
63
+ end
64
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ module DateOperators
5
+ DATE_OPERATORS = {
6
+ "year": "$year",
7
+ "week": "$week",
8
+ "month": "$month",
9
+ "day_of_month": "$dayOfMonth",
10
+ "day_of_week": "$dayOfWeek",
11
+ "day_of_year": "$dayOfYear",
12
+ "iso_day_of_week": "$isoDayOfWeek",
13
+ "iso_week": "$isoWeek",
14
+ "iso_week_Year": "$isoWeekYear"
15
+ }.freeze
16
+
17
+ DATE_OPERATORS.keys.each do |op|
18
+ class_eval <<~RUBY
19
+ def #{op}
20
+ Expression::MethodCall.new DATE_OPERATORS[__method__], self
21
+ end
22
+ RUBY
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ class Expression::Binary < Expression
5
+ attr_accessor :operator, :left_node, :right_node
6
+
7
+ def initialize(operator, left, right)
8
+ @operator = operator
9
+ @left_node = to_expression(left)
10
+ @right_node = to_expression(right)
11
+ end
12
+
13
+ def to_ast
14
+ { operator => [left_node.to_ast, right_node.to_ast] }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../date_operators"
4
+
5
+ module MongoQL
6
+ class Expression::DateNode < Expression
7
+ include DateOperators
8
+
9
+ attr_accessor :expression
10
+
11
+ def initialize(expression)
12
+ @expression = expression
13
+ end
14
+
15
+ def to_ast
16
+ expression.to_ast
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ class Expression::FieldNode < Expression
5
+ attr_accessor :field_name
6
+
7
+ def initialize(name)
8
+ @field_name = name
9
+ end
10
+
11
+ def method_missing(method_name, *args, &block)
12
+ Expression::FieldNode.new("#{field_name}.#{method_name}")
13
+ end
14
+
15
+ def f(field)
16
+ Expression::FieldNode.new("#{field_name}.#{field}")
17
+ end
18
+
19
+ def to_ast
20
+ "$#{field_name}"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ class Expression::MethodCall < Expression
5
+ attr_accessor :method, :target, :ast_template, :args
6
+
7
+ def initialize(method, target, ast_template: nil, **args)
8
+ @target = to_expression(target)
9
+ @method = method
10
+ @ast_template = ast_template
11
+ @args = args
12
+ end
13
+
14
+ def to_ast
15
+ if ast_template
16
+ { method => ast_template.call(target.to_ast, **args) }
17
+ else
18
+ { method => target.to_ast }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ class Expression::Unary < Expression
5
+ attr_accessor :operator, :right_node
6
+
7
+ def initialize(operator, right)
8
+ @operator = operator
9
+ @right_node = to_expression(right)
10
+ end
11
+
12
+ def to_ast
13
+ { operator => right_node.to_ast }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ class Expression::ValueNode < Expression
5
+ attr_accessor :value
6
+
7
+ def initialize(val)
8
+ @value = val
9
+ end
10
+
11
+ def to_ast
12
+ value
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "binary_operators"
4
+ require_relative "unary_operators"
5
+ require_relative "collection_operators"
6
+ require_relative "string_operators"
7
+
8
+ module MongoQL
9
+ class Expression
10
+ include BinaryOperators
11
+ include UnaryOperators
12
+ include CollectionOperators
13
+ include StringOperators
14
+
15
+ FORMATING_OPS = {
16
+ "to_object_id": "$toObjectId",
17
+ "to_id": "$toObjectId",
18
+ "to_s": "$toString",
19
+ "to_string": "$toString",
20
+ "to_int": "$toInt",
21
+ "to_long": "$toLong",
22
+ "to_bool": "$toBool",
23
+ "to_date": "$toDate",
24
+ "to_decimal": "$toDecimal",
25
+ "to_double": "$toDouble",
26
+ "downcase": "$toLower",
27
+ "to_lower": "$toLower",
28
+ "upcase": "$toUpper",
29
+ "to_upper": "$toUpper"
30
+ }.freeze
31
+
32
+ FORMATING_OPS.keys.each do |op|
33
+ class_eval <<~RUBY
34
+ def #{op}
35
+ Expression::MethodCall.new(FORMATING_OPS[__method__], self)
36
+ end
37
+ RUBY
38
+ end
39
+
40
+ def type
41
+ Expression::MethodCall.new "$type", self
42
+ end
43
+
44
+ def if_null(default_val)
45
+ Expression::MethodCall.new "$ifNull", self, ast_template: -> (target, **_args) {
46
+ [target, to_expression(default_val).to_ast]
47
+ }
48
+ end
49
+ alias_method :default, :if_null
50
+
51
+ def as_date
52
+ Expression::DateNode.new(self)
53
+ end
54
+
55
+ def to_ast
56
+ raise NotImplementedError, "#{self.class.name} must implement to_ast"
57
+ end
58
+
59
+ protected
60
+ def to_expression(val)
61
+ if val.is_a?(Expression)
62
+ val
63
+ else
64
+ Expression::ValueNode.new(val)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ module StringOperators
5
+ def substr(start, length)
6
+ Expression::MethodCall.new "$substr", self, ast_template: -> (target, **_args) {
7
+ [target, to_expression(start).to_ast, to_expression(length).to_ast]
8
+ }
9
+ end
10
+
11
+ def trim(chars)
12
+ Expression::MethodCall.new "$trim", self, ast_template: -> (target, **_args) {
13
+ {
14
+ "input" => target,
15
+ "chars" => to_expression(chars).to_ast
16
+ }
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ module UnaryOperators
5
+ UNARY_OPS = {
6
+ "!": "$not"
7
+ }.freeze
8
+
9
+ UNARY_OPS.keys.each do |op|
10
+ class_eval <<~RUBY
11
+ def #{op}
12
+ Expression::Unary.new(UNARY_OPS[__method__], self)
13
+ end
14
+ RUBY
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ VERSION = "0.0.1"
5
+ end
data/lib/mongo_ql.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MongoQL
4
+ end
5
+
6
+ require_relative "mongo_ql/version"
7
+ require_relative "mongo_ql/expression"
8
+ require_relative "mongo_ql/expression/date_note"
9
+ require_relative "mongo_ql/expression/field_node"
10
+ require_relative "mongo_ql/expression/value_node"
11
+ require_relative "mongo_ql/expression/method_call"
12
+ require_relative "mongo_ql/expression/binary"
13
+ require_relative "mongo_ql/expression/unary"
data/mongo_ql.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "mongo_ql/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "mongo_ql"
9
+ spec.version = MongoQL::VERSION
10
+ spec.authors = ["Xizheng Ding"]
11
+ spec.email = ["dingxizheng@gamil.com"]
12
+
13
+ spec.summary = "A DSL for building mongo query in a more natual way"
14
+ spec.homepage = "https://github.com/dingxizheng/mongo_ql"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongo_ql
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Xizheng Ding
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-10-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - dingxizheng@gamil.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rubocop.yml"
22
+ - LICENSE.txt
23
+ - README.md
24
+ - Untitled-1
25
+ - bin/console
26
+ - bin/setup
27
+ - design_specs.md
28
+ - lib/mongo_ql.rb
29
+ - lib/mongo_ql/binary_operators.rb
30
+ - lib/mongo_ql/collection_operators.rb
31
+ - lib/mongo_ql/date_operators.rb
32
+ - lib/mongo_ql/expression.rb
33
+ - lib/mongo_ql/expression/binary.rb
34
+ - lib/mongo_ql/expression/date_note.rb
35
+ - lib/mongo_ql/expression/field_node.rb
36
+ - lib/mongo_ql/expression/method_call.rb
37
+ - lib/mongo_ql/expression/unary.rb
38
+ - lib/mongo_ql/expression/value_node.rb
39
+ - lib/mongo_ql/string_operators.rb
40
+ - lib/mongo_ql/unary_operators.rb
41
+ - lib/mongo_ql/version.rb
42
+ - mongo_ql.gemspec
43
+ homepage: https://github.com/dingxizheng/mongo_ql
44
+ licenses:
45
+ - MIT
46
+ metadata: {}
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubygems_version: 3.0.3
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: A DSL for building mongo query in a more natual way
66
+ test_files: []