mongory 0.7.3-x64-mingw32
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.
Potentially problematic release.
This version of mongory might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +88 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +364 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/LICENSE.txt +21 -0
- data/README.md +488 -0
- data/Rakefile +107 -0
- data/SUBMODULE_INTEGRATION.md +325 -0
- data/docs/advanced_usage.md +40 -0
- data/docs/clang_bridge.md +69 -0
- data/docs/field_names.md +30 -0
- data/docs/migration.md +30 -0
- data/docs/performance.md +61 -0
- data/examples/README.md +41 -0
- data/examples/benchmark-rails.rb +52 -0
- data/examples/benchmark.rb +184 -0
- data/ext/mongory_ext/extconf.rb +91 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/array.h +122 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/config.h +161 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/error.h +79 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/memory_pool.h +95 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/table.h +127 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/value.h +175 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/matchers/matcher.h +76 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core.h +12 -0
- data/ext/mongory_ext/mongory-core/src/foundations/array.c +287 -0
- data/ext/mongory_ext/mongory-core/src/foundations/array_private.h +19 -0
- data/ext/mongory_ext/mongory-core/src/foundations/config.c +270 -0
- data/ext/mongory_ext/mongory-core/src/foundations/config_private.h +48 -0
- data/ext/mongory_ext/mongory-core/src/foundations/error.c +38 -0
- data/ext/mongory_ext/mongory-core/src/foundations/memory_pool.c +298 -0
- data/ext/mongory_ext/mongory-core/src/foundations/string_buffer.c +65 -0
- data/ext/mongory_ext/mongory-core/src/foundations/string_buffer.h +49 -0
- data/ext/mongory_ext/mongory-core/src/foundations/table.c +498 -0
- data/ext/mongory_ext/mongory-core/src/foundations/utils.c +210 -0
- data/ext/mongory_ext/mongory-core/src/foundations/utils.h +70 -0
- data/ext/mongory_ext/mongory-core/src/foundations/value.c +500 -0
- data/ext/mongory_ext/mongory-core/src/matchers/array_record_matcher.c +164 -0
- data/ext/mongory_ext/mongory-core/src/matchers/array_record_matcher.h +47 -0
- data/ext/mongory_ext/mongory-core/src/matchers/base_matcher.c +122 -0
- data/ext/mongory_ext/mongory-core/src/matchers/base_matcher.h +100 -0
- data/ext/mongory_ext/mongory-core/src/matchers/compare_matcher.c +217 -0
- data/ext/mongory_ext/mongory-core/src/matchers/compare_matcher.h +83 -0
- data/ext/mongory_ext/mongory-core/src/matchers/composite_matcher.c +573 -0
- data/ext/mongory_ext/mongory-core/src/matchers/composite_matcher.h +125 -0
- data/ext/mongory_ext/mongory-core/src/matchers/existance_matcher.c +147 -0
- data/ext/mongory_ext/mongory-core/src/matchers/existance_matcher.h +48 -0
- data/ext/mongory_ext/mongory-core/src/matchers/external_matcher.c +124 -0
- data/ext/mongory_ext/mongory-core/src/matchers/external_matcher.h +46 -0
- data/ext/mongory_ext/mongory-core/src/matchers/inclusion_matcher.c +126 -0
- data/ext/mongory_ext/mongory-core/src/matchers/inclusion_matcher.h +46 -0
- data/ext/mongory_ext/mongory-core/src/matchers/literal_matcher.c +314 -0
- data/ext/mongory_ext/mongory-core/src/matchers/literal_matcher.h +97 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher.c +252 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_explainable.c +79 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_explainable.h +23 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_traversable.c +60 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_traversable.h +23 -0
- data/ext/mongory_ext/mongory_ext.c +683 -0
- data/lib/generators/mongory/install/install_generator.rb +42 -0
- data/lib/generators/mongory/install/templates/initializer.rb.erb +83 -0
- data/lib/generators/mongory/matcher/matcher_generator.rb +56 -0
- data/lib/generators/mongory/matcher/templates/matcher.rb.erb +92 -0
- data/lib/generators/mongory/matcher/templates/matcher_spec.rb.erb +17 -0
- data/lib/mongory/c_query_builder.rb +44 -0
- data/lib/mongory/converters/abstract_converter.rb +111 -0
- data/lib/mongory/converters/condition_converter.rb +64 -0
- data/lib/mongory/converters/converted.rb +81 -0
- data/lib/mongory/converters/data_converter.rb +37 -0
- data/lib/mongory/converters/key_converter.rb +87 -0
- data/lib/mongory/converters/value_converter.rb +52 -0
- data/lib/mongory/converters.rb +8 -0
- data/lib/mongory/matchers/abstract_matcher.rb +219 -0
- data/lib/mongory/matchers/abstract_multi_matcher.rb +124 -0
- data/lib/mongory/matchers/and_matcher.rb +72 -0
- data/lib/mongory/matchers/array_record_matcher.rb +93 -0
- data/lib/mongory/matchers/elem_match_matcher.rb +55 -0
- data/lib/mongory/matchers/eq_matcher.rb +46 -0
- data/lib/mongory/matchers/every_matcher.rb +56 -0
- data/lib/mongory/matchers/exists_matcher.rb +53 -0
- data/lib/mongory/matchers/field_matcher.rb +147 -0
- data/lib/mongory/matchers/gt_matcher.rb +41 -0
- data/lib/mongory/matchers/gte_matcher.rb +41 -0
- data/lib/mongory/matchers/hash_condition_matcher.rb +62 -0
- data/lib/mongory/matchers/in_matcher.rb +68 -0
- data/lib/mongory/matchers/literal_matcher.rb +121 -0
- data/lib/mongory/matchers/lt_matcher.rb +41 -0
- data/lib/mongory/matchers/lte_matcher.rb +41 -0
- data/lib/mongory/matchers/ne_matcher.rb +38 -0
- data/lib/mongory/matchers/nin_matcher.rb +68 -0
- data/lib/mongory/matchers/not_matcher.rb +40 -0
- data/lib/mongory/matchers/or_matcher.rb +68 -0
- data/lib/mongory/matchers/present_matcher.rb +55 -0
- data/lib/mongory/matchers/regex_matcher.rb +80 -0
- data/lib/mongory/matchers/size_matcher.rb +54 -0
- data/lib/mongory/matchers.rb +176 -0
- data/lib/mongory/mongoid.rb +19 -0
- data/lib/mongory/query_builder.rb +257 -0
- data/lib/mongory/query_matcher.rb +93 -0
- data/lib/mongory/query_operator.rb +28 -0
- data/lib/mongory/rails.rb +15 -0
- data/lib/mongory/utils/context.rb +48 -0
- data/lib/mongory/utils/debugger.rb +125 -0
- data/lib/mongory/utils/rails_patch.rb +22 -0
- data/lib/mongory/utils/singleton_builder.rb +31 -0
- data/lib/mongory/utils.rb +76 -0
- data/lib/mongory/version.rb +5 -0
- data/lib/mongory.rb +123 -0
- data/lib/mongory_ext.so +0 -0
- data/mongory.gemspec +62 -0
- data/scripts/build_with_core.sh +292 -0
- data/sig/mongory.rbs +4 -0
- metadata +159 -0
@@ -0,0 +1,325 @@
|
|
1
|
+
# Mongory-rb Submodule Integration Guide
|
2
|
+
|
3
|
+
This document describes how to integrate `mongory-core` as a Git submodule into `mongory-rb` to enable a high-performance C extension.
|
4
|
+
|
5
|
+
## Architecture Overview
|
6
|
+
|
7
|
+
```
|
8
|
+
mongory-rb/
|
9
|
+
├── lib/ # Ruby code
|
10
|
+
│ ├── mongory.rb # Entry, loads the C extension
|
11
|
+
│ └── mongory/ # Other Ruby modules
|
12
|
+
├── ext/ # C extension
|
13
|
+
│ └── mongory_ext/
|
14
|
+
│ ├── mongory-core/ # Git submodule (sources only; no prior CMake build required)
|
15
|
+
│ ├── extconf.rb # Build configuration (compiles submodule .c sources directly)
|
16
|
+
│ └── mongory_ext.c # Ruby C wrapper
|
17
|
+
└── scripts/
|
18
|
+
└── build_with_core.sh # (Optional) build script
|
19
|
+
```
|
20
|
+
|
21
|
+
## Quick Start
|
22
|
+
|
23
|
+
### 1. Clone and initialize
|
24
|
+
|
25
|
+
```bash
|
26
|
+
# Clone the project
|
27
|
+
git clone <your-mongory-rb-repo>
|
28
|
+
cd mongory-rb
|
29
|
+
|
30
|
+
# Initialize the submodule
|
31
|
+
git submodule update --init --recursive
|
32
|
+
```
|
33
|
+
|
34
|
+
### 2. Install system dependencies
|
35
|
+
|
36
|
+
Installing `mongory-rb` (with the C extension) only requires basic build tools and Ruby headers:
|
37
|
+
|
38
|
+
**macOS:**
|
39
|
+
```bash
|
40
|
+
xcode-select --install # Install Xcode Command Line Tools (includes clang)
|
41
|
+
```
|
42
|
+
|
43
|
+
**Ubuntu/Debian:**
|
44
|
+
```bash
|
45
|
+
sudo apt update
|
46
|
+
sudo apt install build-essential ruby-dev
|
47
|
+
```
|
48
|
+
|
49
|
+
**CentOS/RHEL/Fedora:**
|
50
|
+
```bash
|
51
|
+
sudo yum groupinstall "Development Tools" || sudo dnf groupinstall "Development Tools"
|
52
|
+
sudo yum install ruby-devel || sudo dnf install ruby-devel
|
53
|
+
```
|
54
|
+
|
55
|
+
> Optional: CMake and cJSON are only needed if you want to run the core tests/benchmarks inside the `mongory-core` submodule (e.g., via CMake/ctest).
|
56
|
+
|
57
|
+
### 3. Build the project
|
58
|
+
|
59
|
+
Using Rake (recommended):
|
60
|
+
|
61
|
+
```bash
|
62
|
+
# Automatically initializes the submodule and builds the C extension (no prior CMake build needed)
|
63
|
+
bundle exec rake build_all
|
64
|
+
|
65
|
+
# If rake-compiler is not available, the fallback :compile will directly run extconf.rb + make
|
66
|
+
```
|
67
|
+
|
68
|
+
Or use the script (optional):
|
69
|
+
|
70
|
+
```bash
|
71
|
+
./scripts/build_with_core.sh # Basic build
|
72
|
+
./scripts/build_with_core.sh --debug # Debug build
|
73
|
+
./scripts/build_with_core.sh --help # Show all options
|
74
|
+
```
|
75
|
+
|
76
|
+
## Detailed Steps
|
77
|
+
|
78
|
+
### Submodule management
|
79
|
+
|
80
|
+
```bash
|
81
|
+
# Initialize submodule
|
82
|
+
rake submodule:init
|
83
|
+
|
84
|
+
# Update submodule to latest
|
85
|
+
rake submodule:update
|
86
|
+
|
87
|
+
# Manually update submodule
|
88
|
+
git submodule update --remote
|
89
|
+
```
|
90
|
+
|
91
|
+
### Manual build flow (without rake-compiler)
|
92
|
+
|
93
|
+
If you prefer to control the build manually:
|
94
|
+
|
95
|
+
```bash
|
96
|
+
# 1. Ensure submodule is initialized
|
97
|
+
git submodule update --init --recursive
|
98
|
+
|
99
|
+
# 2. (Optional) Only needed if you run core tests/benchmarks inside the submodule
|
100
|
+
# Note: This step requires cJSON; typical mongory-rb usage does not.
|
101
|
+
# cd ext/mongory_ext/mongory-core
|
102
|
+
# ./build.sh --test
|
103
|
+
# cd ../../..
|
104
|
+
|
105
|
+
# 3. Build the Ruby C extension (compiles submodule sources directly via extconf.rb)
|
106
|
+
cd ext/mongory_ext
|
107
|
+
ruby extconf.rb
|
108
|
+
make
|
109
|
+
cd ../..
|
110
|
+
|
111
|
+
# 4. Run tests
|
112
|
+
bundle exec rspec
|
113
|
+
```
|
114
|
+
|
115
|
+
### Clean builds
|
116
|
+
|
117
|
+
```bash
|
118
|
+
# Clean all build artifacts
|
119
|
+
rake clean_all
|
120
|
+
|
121
|
+
# Or use the build script
|
122
|
+
./scripts/build_with_core.sh --clean
|
123
|
+
```
|
124
|
+
|
125
|
+
## Development Guide
|
126
|
+
|
127
|
+
### Modify the C extension
|
128
|
+
|
129
|
+
1. Edit `ext/mongory_ext/mongory_ext.c`
|
130
|
+
2. Rebuild:
|
131
|
+
```bash
|
132
|
+
cd ext/mongory_ext
|
133
|
+
make
|
134
|
+
```
|
135
|
+
|
136
|
+
### Update mongory-core
|
137
|
+
|
138
|
+
1. Enter the submodule directory:
|
139
|
+
```bash
|
140
|
+
cd ext/mongory_ext/mongory-core
|
141
|
+
```
|
142
|
+
|
143
|
+
2. Checkout the desired version or branch:
|
144
|
+
```bash
|
145
|
+
git checkout main
|
146
|
+
git pull origin main
|
147
|
+
```
|
148
|
+
|
149
|
+
3. Return to the main project and commit the submodule update:
|
150
|
+
```bash
|
151
|
+
cd ../../..
|
152
|
+
git add ext/mongory_ext/mongory-core
|
153
|
+
git commit -m "Update mongory-core submodule"
|
154
|
+
```
|
155
|
+
|
156
|
+
### Debug the C extension
|
157
|
+
|
158
|
+
```bash
|
159
|
+
# Build in debug mode
|
160
|
+
export DEBUG=1
|
161
|
+
cd ext/mongory_ext
|
162
|
+
ruby extconf.rb
|
163
|
+
make
|
164
|
+
|
165
|
+
# Or use the build script
|
166
|
+
./scripts/build_with_core.sh --debug
|
167
|
+
```
|
168
|
+
|
169
|
+
Debug mode will:
|
170
|
+
- Enable debug symbols (`-g`)
|
171
|
+
- Disable optimizations (`-O0`)
|
172
|
+
- Define the `DEBUG` macro
|
173
|
+
|
174
|
+
### C extension API (current public surface)
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
require 'mongory'
|
178
|
+
|
179
|
+
condition = { "age" => { "$gt" => 18 } }
|
180
|
+
matcher = Mongory::CMatcher.new(condition)
|
181
|
+
|
182
|
+
data = { "name" => "John", "age" => 25 }
|
183
|
+
result = matcher.match(data) # => true/false
|
184
|
+
|
185
|
+
# Optional: get explanation (runs explain on the C side, currently returns nil)
|
186
|
+
matcher.explain
|
187
|
+
```
|
188
|
+
|
189
|
+
## Troubleshooting
|
190
|
+
|
191
|
+
### Common issues
|
192
|
+
|
193
|
+
**1. Submodule is empty**
|
194
|
+
```bash
|
195
|
+
# Fix
|
196
|
+
git submodule update --init --recursive
|
197
|
+
```
|
198
|
+
|
199
|
+
**2. cJSON library not found (only required if you run mongory-core CMake tests)**
|
200
|
+
```bash
|
201
|
+
# macOS
|
202
|
+
brew install cjson
|
203
|
+
|
204
|
+
# Ubuntu/Debian
|
205
|
+
sudo apt install libcjson-dev
|
206
|
+
|
207
|
+
# Verify installation
|
208
|
+
pkg-config --exists libcjson && echo "Found" || echo "Not found"
|
209
|
+
```
|
210
|
+
|
211
|
+
**3. Build errors**
|
212
|
+
```bash
|
213
|
+
# Clean and rebuild
|
214
|
+
./scripts/build_with_core.sh --clean
|
215
|
+
./scripts/build_with_core.sh --debug
|
216
|
+
```
|
217
|
+
|
218
|
+
**4. C extension fails to load**
|
219
|
+
- Check Ruby version compatibility (>= 2.6.0)
|
220
|
+
- Ensure all system deps are installed
|
221
|
+
- Inspect error messages and compiler warnings
|
222
|
+
|
223
|
+
### Logging and debugging
|
224
|
+
|
225
|
+
Enable verbose output:
|
226
|
+
```bash
|
227
|
+
# Verbose during build
|
228
|
+
VERBOSE=1 ./scripts/build_with_core.sh
|
229
|
+
|
230
|
+
# Debug info when loading Ruby
|
231
|
+
RUBY_DEBUG=1 ruby -rmongory -e "puts Mongory::CoreInterface.version"
|
232
|
+
```
|
233
|
+
|
234
|
+
### Performance check
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
require 'benchmark'
|
238
|
+
require 'mongory'
|
239
|
+
|
240
|
+
records = 10000.times.map { |i| { "id" => i, "age" => rand(18..65) } }
|
241
|
+
|
242
|
+
|
243
|
+
```
|
244
|
+
|
245
|
+
## CI/CD integration
|
246
|
+
|
247
|
+
### GitHub Actions example
|
248
|
+
|
249
|
+
```yaml
|
250
|
+
name: Build and Test
|
251
|
+
|
252
|
+
on: [push, pull_request]
|
253
|
+
|
254
|
+
jobs:
|
255
|
+
test:
|
256
|
+
runs-on: ubuntu-latest
|
257
|
+
strategy:
|
258
|
+
matrix:
|
259
|
+
ruby-version: ['2.6', '2.7', '3.0', '3.1']
|
260
|
+
|
261
|
+
steps:
|
262
|
+
- uses: actions/checkout@v3
|
263
|
+
with:
|
264
|
+
submodules: recursive
|
265
|
+
|
266
|
+
- name: Set up Ruby
|
267
|
+
uses: ruby/setup-ruby@v1
|
268
|
+
with:
|
269
|
+
ruby-version: ${{ matrix.ruby-version }}
|
270
|
+
bundler-cache: true
|
271
|
+
|
272
|
+
- name: Install system dependencies
|
273
|
+
run: |
|
274
|
+
sudo apt update
|
275
|
+
sudo apt install -y build-essential ruby-dev
|
276
|
+
|
277
|
+
- name: Build with C extension
|
278
|
+
run: bundle exec rake build_all
|
279
|
+
|
280
|
+
- name: Run tests
|
281
|
+
run: bundle exec rspec
|
282
|
+
|
283
|
+
# Only needed if you also run mongory-core C tests/benchmarks (optional):
|
284
|
+
# - name: Install CMake & cJSON (only if running core tests)
|
285
|
+
# run: sudo apt install -y cmake libcjson-dev
|
286
|
+
# - name: Build mongory-core tests (optional)
|
287
|
+
# run: |
|
288
|
+
# cd ext/mongory_ext/mongory-core
|
289
|
+
# ./build.sh --test
|
290
|
+
```
|
291
|
+
|
292
|
+
## Contributing Guide
|
293
|
+
|
294
|
+
### Development workflow
|
295
|
+
|
296
|
+
1. Fork this repository
|
297
|
+
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
298
|
+
3. If you modify C code, make sure to update tests
|
299
|
+
4. Run the full test suite: `./scripts/build_with_core.sh`
|
300
|
+
5. Commit changes: `git commit -m 'Add amazing feature'`
|
301
|
+
6. Push the branch: `git push origin feature/amazing-feature`
|
302
|
+
7. Open a Pull Request
|
303
|
+
|
304
|
+
### Coding standards
|
305
|
+
|
306
|
+
- **C code**: C99, follow mongory-core style
|
307
|
+
- **Ruby code**: follow project RuboCop config
|
308
|
+
- **Docs**: document all public APIs
|
309
|
+
|
310
|
+
### Testing requirements
|
311
|
+
|
312
|
+
- Add tests for all new features
|
313
|
+
- Ensure both C extension and Ruby fallback are covered
|
314
|
+
- Run benchmarks to prevent regressions
|
315
|
+
|
316
|
+
## References
|
317
|
+
|
318
|
+
- [mongory-core doc](https://github.com/mongoryhq/mongory-core)
|
319
|
+
- [Ruby C extension doc](https://docs.ruby-lang.org/en/master/extension_rdoc.html)
|
320
|
+
- [Git Submodules doc](https://git-scm.com/book/en/v2/Git-Tools-Submodules)
|
321
|
+
- [CMake doc](https://cmake.org/documentation/)
|
322
|
+
|
323
|
+
## License
|
324
|
+
|
325
|
+
This integration follows the MIT license, consistent with mongory-core and mongory-rb.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Advanced Usage
|
2
|
+
|
3
|
+
## Complex Queries
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
# Nested conditions
|
7
|
+
users.mongory
|
8
|
+
.where(
|
9
|
+
:age.gte => 18,
|
10
|
+
:$or => [
|
11
|
+
{ :status => 'active' },
|
12
|
+
{ :status => 'pending', :created_at.gte => 1.week.ago }
|
13
|
+
]
|
14
|
+
)
|
15
|
+
|
16
|
+
# Using any_of for nested OR conditions
|
17
|
+
users.mongory
|
18
|
+
.where(:age.gte => 18)
|
19
|
+
.any_of(
|
20
|
+
{ :status => 'active' },
|
21
|
+
{ :status => 'pending', :created_at.gte => 1.week.ago }
|
22
|
+
)
|
23
|
+
|
24
|
+
# Array operations
|
25
|
+
posts.mongory
|
26
|
+
.where(:tags.elem_match => { :name => 'ruby', :priority.gt => 5 })
|
27
|
+
.where(:comments.every => { :approved => true })
|
28
|
+
```
|
29
|
+
|
30
|
+
## Integration with ActiveRecord
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class User < ActiveRecord::Base
|
34
|
+
def active_friends
|
35
|
+
friends.mongory
|
36
|
+
.where(:status => 'active')
|
37
|
+
.where(:last_seen.gte => 1.day.ago)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Clang Bridge (C Extension)
|
2
|
+
|
3
|
+
The Clang bridge connects the Ruby DSL to the `mongory-core` engine via a compact C layer. It exposes two key entry points:
|
4
|
+
|
5
|
+
- `Mongory::CMatcher`: a low-level matcher API backed by C.
|
6
|
+
- `QueryBuilder#c`: an ergonomic switch that reuses your current Ruby condition and executes it through `CMatcher`.
|
7
|
+
|
8
|
+
## Build/Install
|
9
|
+
|
10
|
+
```bash
|
11
|
+
bundle install
|
12
|
+
bundle exec rake compile
|
13
|
+
# or, when installing the gem, the extension will compile automatically if toolchain is present
|
14
|
+
```
|
15
|
+
|
16
|
+
## Quick check
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
require 'mongory'
|
20
|
+
if defined?(Mongory::CMatcher)
|
21
|
+
puts 'C extension available'
|
22
|
+
else
|
23
|
+
puts 'C extension not available, using pure Ruby'
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
## Basic usage
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
records = [
|
31
|
+
{ 'name' => 'Jack', 'age' => 18 },
|
32
|
+
{ 'name' => 'Jill', 'age' => 15 },
|
33
|
+
{ 'name' => 'Bob', 'age' => 21 }
|
34
|
+
]
|
35
|
+
|
36
|
+
# Switch existing Ruby query to C path
|
37
|
+
query = records.mongory.c # => returns Mongory::CQueryBuilder
|
38
|
+
.where(:age.gte => 18)
|
39
|
+
|
40
|
+
query.each.to_a # enumerate matches via C
|
41
|
+
query.fast.to_a # alias of each
|
42
|
+
query.trace.to_a # print value compare progression
|
43
|
+
query.explain # print core-level matcher tree
|
44
|
+
|
45
|
+
# Or use CMatcher directly
|
46
|
+
matcher = Mongory::CMatcher.new(:age.gte => 18)
|
47
|
+
records.select { |r| matcher.match?(r) }
|
48
|
+
```
|
49
|
+
|
50
|
+
## Tracing and debugging
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
matcher = Mongory::CMatcher.new(:$or => [ { :name.regex => /^J/ }, { :age.gt => 20 } ])
|
54
|
+
matcher.enable_trace
|
55
|
+
records.each { |r| matcher.match?(r) }
|
56
|
+
matcher.print_trace # prints detailed trace
|
57
|
+
matcher.disable_trace
|
58
|
+
|
59
|
+
# Or trace single record compare progression
|
60
|
+
matcher.trace(records.first)
|
61
|
+
```
|
62
|
+
|
63
|
+
## Notes
|
64
|
+
|
65
|
+
- Regexes use Ruby's `Regexp` internally; string patterns are compiled once and cached.
|
66
|
+
- Context (`Mongory::Utils::Context`) is shared between Ruby and C during matching, enabling custom converters.
|
67
|
+
- If the extension fails to load, `Mongory::CQueryBuilder` is unavailable and `.c` will not be used; the Ruby path continues to work.
|
68
|
+
|
69
|
+
|
data/docs/field_names.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Handling Dots in Field Names
|
2
|
+
|
3
|
+
Mongory supports field names containing dots, which require escaping:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
# Sample data
|
7
|
+
records = [
|
8
|
+
{ "user.name" => "John", "age" => 25 }, # Field name contains a dot
|
9
|
+
{ "user" => { "name" => "Bob" }, "age" => 30 } # Nested field
|
10
|
+
]
|
11
|
+
|
12
|
+
# Field name contains a dot
|
13
|
+
records.mongory.where("user\\.name" => "John") # Two backslashes needed with double quotes
|
14
|
+
# => [{ "user.name" => "John", "age" => 25 }]
|
15
|
+
|
16
|
+
# or
|
17
|
+
records.mongory.where('user\.name' => "John") # One backslash needed with single quotes
|
18
|
+
# => [{ "user.name" => "John", "age" => 25 }]
|
19
|
+
|
20
|
+
# Nested field (no escaping needed)
|
21
|
+
records.mongory.where("user.name" => "Bob")
|
22
|
+
# => [{ "user" => { "name" => "Bob" }, "age" => 30 }]
|
23
|
+
```
|
24
|
+
|
25
|
+
Notes:
|
26
|
+
- With double quotes, backslashes need to be escaped (`\\`)
|
27
|
+
- With single quotes, backslashes don't need to be escaped (`\`)
|
28
|
+
- This behavior is consistent with MongoDB's query syntax
|
29
|
+
- The escaped dot pattern (`\.`) matches fields where the dot is part of the field name
|
30
|
+
- The unescaped dot pattern (`.`) matches nested fields in the document structure
|
data/docs/migration.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Migration Guide
|
2
|
+
|
3
|
+
## From Array#select
|
4
|
+
```ruby
|
5
|
+
# Before
|
6
|
+
records.select { |r| r['age'] >= 18 && r['status'] == 'active' }
|
7
|
+
|
8
|
+
# After
|
9
|
+
records.mongory.where(:age.gte => 18, status: 'active')
|
10
|
+
```
|
11
|
+
|
12
|
+
## From ActiveRecord
|
13
|
+
```ruby
|
14
|
+
# Before
|
15
|
+
indexed_query.where("age >= ? AND status = ?", 18, 'active')
|
16
|
+
|
17
|
+
# After
|
18
|
+
indexed_query.mongory.where(:age.gte => 18, status: 'active')
|
19
|
+
```
|
20
|
+
|
21
|
+
## From MongoDB
|
22
|
+
```ruby
|
23
|
+
# Before (MongoDB)
|
24
|
+
users.where(:age.gte => 18, status: 'active')
|
25
|
+
|
26
|
+
# After (Mongory)
|
27
|
+
users.mongory.where(:age.gte => 18, status: 'active')
|
28
|
+
|
29
|
+
# Just the same.
|
30
|
+
```
|
data/docs/performance.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Performance & Benchmarks
|
2
|
+
|
3
|
+
## C Extension vs Pure Ruby
|
4
|
+
|
5
|
+
- C extension provides 3-10x performance improvement for large datasets
|
6
|
+
- Automatic fallback to pure Ruby if C extension unavailable
|
7
|
+
- Check availability: `defined?(Mongory::CMatcher)` or attempt to require the extension
|
8
|
+
- Memory management handled by mongory-core's memory pool
|
9
|
+
|
10
|
+
## Memory Usage
|
11
|
+
|
12
|
+
- Mongory operates entirely in memory
|
13
|
+
- Consider your data size and memory constraints
|
14
|
+
- Proc-based implementation reduces memory usage
|
15
|
+
- Context system provides better memory management
|
16
|
+
|
17
|
+
## Query Optimization
|
18
|
+
|
19
|
+
- Complex conditions are evaluated in sequence
|
20
|
+
- Use `explain` to analyze query performance
|
21
|
+
- Empty conditions are optimized with cached Procs
|
22
|
+
- Context system allows fine-grained control over conversion
|
23
|
+
|
24
|
+
## Benchmarks
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
# Plain Ruby Simple query (100000 records)
|
28
|
+
records.select { |r| r['age'].is_a?(Numeric) && r['age'] >= 18 } # ~9ms
|
29
|
+
|
30
|
+
# Plain Ruby Complex query (100000 records)
|
31
|
+
records.select do |r|
|
32
|
+
next false unless r.key?('age') && r.key?('status')
|
33
|
+
|
34
|
+
r['age'].is_a?(Numeric) && r['age'] >= 18 || r['status'] == 'active'
|
35
|
+
end # ~20ms
|
36
|
+
|
37
|
+
# Simple query (100000 records)
|
38
|
+
records.mongory.where(:age.gte => 18) # ~119ms
|
39
|
+
|
40
|
+
# Complex query (100000 records)
|
41
|
+
records.mongory.where(:$or => [{:age.gte => 18}, {:status => 'active'}]) # ~107ms
|
42
|
+
|
43
|
+
# Complex query with fast mode (100000 records)
|
44
|
+
records.mongory.where(:$or => [{:age.gte => 18}, {:status => 'active'}]).fast # ~63ms
|
45
|
+
|
46
|
+
# Simple query with C extension (100000 records)
|
47
|
+
records.mongory.c.where(:age.gte => 18) # ~15ms
|
48
|
+
# Complex query with C extension (100000 records)
|
49
|
+
records.mongory.c.where(:$or => [{:age.gte => 18}, {:status => 'active'}]) # ~23ms, same with plain ruby
|
50
|
+
```
|
51
|
+
|
52
|
+
Note: Performance varies based on:
|
53
|
+
|
54
|
+
- Data size
|
55
|
+
- Query complexity
|
56
|
+
- Hardware specifications
|
57
|
+
- Ruby version
|
58
|
+
|
59
|
+
Benchmark in your environment to validate.
|
60
|
+
|
61
|
+
|
data/examples/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Examples
|
2
|
+
|
3
|
+
This directory contains example scripts demonstrating Mongory's features and capabilities.
|
4
|
+
|
5
|
+
## Performance Benchmark
|
6
|
+
|
7
|
+
`benchmark.rb` demonstrates Mongory's performance characteristics with different data sizes and query complexities.
|
8
|
+
|
9
|
+
### Usage
|
10
|
+
|
11
|
+
```bash
|
12
|
+
ruby examples/benchmark.rb
|
13
|
+
```
|
14
|
+
|
15
|
+
### What it tests
|
16
|
+
|
17
|
+
1. Simple queries with different data sizes:
|
18
|
+
- 1000 records
|
19
|
+
- 10000 records
|
20
|
+
- 100000 records
|
21
|
+
|
22
|
+
2. Complex queries with different data sizes:
|
23
|
+
- OR conditions
|
24
|
+
- Nested conditions
|
25
|
+
|
26
|
+
### Output
|
27
|
+
|
28
|
+
The script outputs execution times for each test case, helping you understand:
|
29
|
+
- How query complexity affects performance
|
30
|
+
- How data size impacts execution time
|
31
|
+
- The relative performance of different query types
|
32
|
+
|
33
|
+
### Note
|
34
|
+
|
35
|
+
Results may vary based on:
|
36
|
+
- Hardware specifications
|
37
|
+
- Ruby version
|
38
|
+
- System load
|
39
|
+
- Other factors
|
40
|
+
|
41
|
+
Run the benchmark in your environment to get accurate performance data for your use case.
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
puts 'Ruby String#empty?'
|
7
|
+
result = Benchmark.measure do
|
8
|
+
1_000_000.times do
|
9
|
+
''.empty?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
puts result
|
13
|
+
|
14
|
+
puts 'Rails String#blank?'
|
15
|
+
result = Benchmark.measure do
|
16
|
+
1_000_000.times do
|
17
|
+
''.blank?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
puts result
|
21
|
+
|
22
|
+
puts 'Ruby Array#empty?'
|
23
|
+
result = Benchmark.measure do
|
24
|
+
1_000_000.times do
|
25
|
+
[].empty?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
puts result
|
29
|
+
|
30
|
+
puts 'Rails Array#blank?'
|
31
|
+
result = Benchmark.measure do
|
32
|
+
1_000_000.times do
|
33
|
+
[].blank?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
puts result
|
37
|
+
|
38
|
+
puts 'Ruby Hash#empty?'
|
39
|
+
result = Benchmark.measure do
|
40
|
+
1_000_000.times do
|
41
|
+
{}.empty?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
puts result
|
45
|
+
|
46
|
+
puts 'Rails Hash#blank?'
|
47
|
+
result = Benchmark.measure do
|
48
|
+
1_000_000.times do
|
49
|
+
{}.blank?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
puts result
|