expressir 2.1.30 → 2.1.31
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.
- checksums.yaml +4 -4
- data/.github/workflows/docs.yml +98 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/rake.yml +4 -0
- data/.github/workflows/release.yml +5 -0
- data/.github/workflows/validate_schemas.yml +1 -1
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +244 -39
- data/Gemfile +2 -1
- data/README.adoc +621 -54
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +683 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/index.adoc +221 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +84 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/expressir.gemspec +2 -0
- data/lib/expressir/cli.rb +12 -4
- data/lib/expressir/commands/manifest.rb +427 -0
- data/lib/expressir/commands/package.rb +1274 -0
- data/lib/expressir/commands/validate.rb +70 -37
- data/lib/expressir/commands/validate_ascii.rb +607 -0
- data/lib/expressir/commands/validate_load.rb +88 -0
- data/lib/expressir/express/formatter.rb +5 -1
- data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
- data/lib/expressir/express/parser.rb +33 -0
- data/lib/expressir/manifest/resolver.rb +213 -0
- data/lib/expressir/manifest/validator.rb +195 -0
- data/lib/expressir/model/declarations/entity.rb +6 -0
- data/lib/expressir/model/dependency_resolver.rb +270 -0
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/repository.rb +400 -5
- data/lib/expressir/model/repository_validator.rb +295 -0
- data/lib/expressir/model/search_engine.rb +525 -0
- data/lib/expressir/model.rb +4 -94
- data/lib/expressir/package/builder.rb +200 -0
- data/lib/expressir/package/metadata.rb +81 -0
- data/lib/expressir/package/reader.rb +165 -0
- data/lib/expressir/schema_manifest.rb +11 -1
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +15 -2
- metadata +114 -4
- data/docs/benchmarking.adoc +0 -107
- data/docs/liquid_drops.adoc +0 -1547
|
@@ -0,0 +1,826 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Querying Packages
|
|
3
|
+
parent: LER Packages
|
|
4
|
+
grand_parent: Guides
|
|
5
|
+
nav_order: 3
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
= Querying Packages
|
|
9
|
+
|
|
10
|
+
== Purpose
|
|
11
|
+
|
|
12
|
+
This guide explains how to search and query LER package contents using both the
|
|
13
|
+
SearchEngine API and CLI commands. LER packages include pre-built indexes for
|
|
14
|
+
efficient querying.
|
|
15
|
+
|
|
16
|
+
== References
|
|
17
|
+
|
|
18
|
+
* link:index.html[LER Packages Overview]
|
|
19
|
+
* link:loading-packages.html[Loading Packages]
|
|
20
|
+
* link:../ruby-api/search-engine.html[Search Engine API]
|
|
21
|
+
* link:../ruby-api/working-with-repository.html[Working with Repository]
|
|
22
|
+
|
|
23
|
+
== Concepts
|
|
24
|
+
|
|
25
|
+
Search engine:: The [`SearchEngine`](../../lib/expressir/model/search_engine.rb:7)
|
|
26
|
+
class provides pattern matching and filtering capabilities for EXPRESS elements.
|
|
27
|
+
|
|
28
|
+
Pattern matching:: Supports simple names, qualified paths, wildcards, prefix
|
|
29
|
+
matching, and regular expressions.
|
|
30
|
+
|
|
31
|
+
Element types:: Schema, entity, type, attribute, function, procedure, rule,
|
|
32
|
+
constant, parameter, variable, and more.
|
|
33
|
+
|
|
34
|
+
Type categories:: Classification of types as select, enumeration, aggregate, or
|
|
35
|
+
defined types.
|
|
36
|
+
|
|
37
|
+
Pre-built indexes:: Entity, type, and reference indexes stored in the package
|
|
38
|
+
for fast lookups.
|
|
39
|
+
|
|
40
|
+
== Using SearchEngine with packages
|
|
41
|
+
|
|
42
|
+
=== Basic search engine usage
|
|
43
|
+
|
|
44
|
+
Load a package and create a search engine:
|
|
45
|
+
|
|
46
|
+
[source,ruby]
|
|
47
|
+
----
|
|
48
|
+
require "expressir"
|
|
49
|
+
|
|
50
|
+
# Load package
|
|
51
|
+
repo = Expressir::Model::Repository.from_package("schemas.ler")
|
|
52
|
+
|
|
53
|
+
# Create search engine
|
|
54
|
+
engine = Expressir::Model::SearchEngine.new(repo)
|
|
55
|
+
|
|
56
|
+
# Search for elements
|
|
57
|
+
results = engine.search(pattern: "action")
|
|
58
|
+
puts "Found #{results.size} results"
|
|
59
|
+
----
|
|
60
|
+
|
|
61
|
+
=== Listing all elements
|
|
62
|
+
|
|
63
|
+
List elements by type:
|
|
64
|
+
|
|
65
|
+
[source,ruby]
|
|
66
|
+
----
|
|
67
|
+
# List all entities
|
|
68
|
+
entities = engine.list(type: "entity")
|
|
69
|
+
puts "Total entities: #{entities.size}"
|
|
70
|
+
|
|
71
|
+
entities.each do |e|
|
|
72
|
+
puts " #{e[:schema]}.#{e[:id]}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# List all types
|
|
76
|
+
types = engine.list(type: "type")
|
|
77
|
+
puts "Total types: #{types.size}"
|
|
78
|
+
|
|
79
|
+
# List functions
|
|
80
|
+
functions = engine.list(type: "function")
|
|
81
|
+
puts "Total functions: #{functions.size}"
|
|
82
|
+
----
|
|
83
|
+
|
|
84
|
+
=== Filtering by schema
|
|
85
|
+
|
|
86
|
+
Limit results to specific schema:
|
|
87
|
+
|
|
88
|
+
[source,ruby]
|
|
89
|
+
----
|
|
90
|
+
# Entities from specific schema
|
|
91
|
+
entities = engine.list(type: "entity", schema: "action_schema")
|
|
92
|
+
puts "Entities in action_schema: #{entities.size}"
|
|
93
|
+
|
|
94
|
+
# Types from specific schema
|
|
95
|
+
types = engine.list(type: "type", schema: "approval_schema")
|
|
96
|
+
puts "Types in approval_schema: #{types.size}"
|
|
97
|
+
----
|
|
98
|
+
|
|
99
|
+
=== Filtering types by category
|
|
100
|
+
|
|
101
|
+
Filter types by their category:
|
|
102
|
+
|
|
103
|
+
[source,ruby]
|
|
104
|
+
----
|
|
105
|
+
# List SELECT types
|
|
106
|
+
select_types = engine.list(type: "type", category: "select")
|
|
107
|
+
puts "SELECT types: #{select_types.size}"
|
|
108
|
+
|
|
109
|
+
# List ENUMERATION types
|
|
110
|
+
enum_types = engine.list(type: "type", category: "enumeration")
|
|
111
|
+
puts "ENUMERATION types: #{enum_types.size}"
|
|
112
|
+
|
|
113
|
+
# List AGGREGATE types
|
|
114
|
+
agg_types = engine.list(type: "type", category: "aggregate")
|
|
115
|
+
puts "AGGREGATE types: #{agg_types.size}"
|
|
116
|
+
|
|
117
|
+
# List defined types
|
|
118
|
+
defined_types = engine.list(type: "type", category: "defined")
|
|
119
|
+
puts "Defined types: #{defined_types.size}"
|
|
120
|
+
----
|
|
121
|
+
|
|
122
|
+
== Search patterns
|
|
123
|
+
|
|
124
|
+
=== Simple name search
|
|
125
|
+
|
|
126
|
+
Search by element name:
|
|
127
|
+
|
|
128
|
+
[source,ruby]
|
|
129
|
+
----
|
|
130
|
+
# Find all elements containing "action"
|
|
131
|
+
results = engine.search(pattern: "action")
|
|
132
|
+
|
|
133
|
+
results.each do |r|
|
|
134
|
+
puts "#{r[:type]}: #{r[:path]}"
|
|
135
|
+
end
|
|
136
|
+
----
|
|
137
|
+
|
|
138
|
+
=== Qualified name search
|
|
139
|
+
|
|
140
|
+
Search using qualified paths:
|
|
141
|
+
|
|
142
|
+
[source,ruby]
|
|
143
|
+
----
|
|
144
|
+
# Search for schema.element
|
|
145
|
+
results = engine.search(pattern: "action_schema.action")
|
|
146
|
+
|
|
147
|
+
# Search for schema.entity.attribute
|
|
148
|
+
results = engine.search(pattern: "action_schema.action.id")
|
|
149
|
+
----
|
|
150
|
+
|
|
151
|
+
=== Wildcard patterns
|
|
152
|
+
|
|
153
|
+
Use `*` for wildcard matching:
|
|
154
|
+
|
|
155
|
+
[source,ruby]
|
|
156
|
+
----
|
|
157
|
+
# Wildcard schema, specific element
|
|
158
|
+
results = engine.search(pattern: "*.action")
|
|
159
|
+
|
|
160
|
+
# Specific schema, wildcard element
|
|
161
|
+
results = engine.search(pattern: "action_schema.*")
|
|
162
|
+
|
|
163
|
+
# Multi-level wildcards
|
|
164
|
+
results = engine.search(pattern: "*.*.id")
|
|
165
|
+
|
|
166
|
+
# All elements
|
|
167
|
+
results = engine.search(pattern: "*")
|
|
168
|
+
----
|
|
169
|
+
|
|
170
|
+
=== Prefix matching
|
|
171
|
+
|
|
172
|
+
Match elements starting with a prefix:
|
|
173
|
+
|
|
174
|
+
[source,ruby]
|
|
175
|
+
----
|
|
176
|
+
# Find all elements starting with "action"
|
|
177
|
+
results = engine.search(pattern: "action*")
|
|
178
|
+
|
|
179
|
+
# Combine with schema
|
|
180
|
+
results = engine.search(pattern: "action_schema.action*")
|
|
181
|
+
----
|
|
182
|
+
|
|
183
|
+
=== Regular expression search
|
|
184
|
+
|
|
185
|
+
Use regex for complex patterns:
|
|
186
|
+
|
|
187
|
+
[source,ruby]
|
|
188
|
+
----
|
|
189
|
+
# Search with regex
|
|
190
|
+
results = engine.search(
|
|
191
|
+
pattern: "action|approval",
|
|
192
|
+
regex: true
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# Case-sensitive regex
|
|
196
|
+
results = engine.search(
|
|
197
|
+
pattern: "^Action[A-Z]",
|
|
198
|
+
regex: true,
|
|
199
|
+
case_sensitive: true
|
|
200
|
+
)
|
|
201
|
+
----
|
|
202
|
+
|
|
203
|
+
=== Exact matching
|
|
204
|
+
|
|
205
|
+
Require exact name matches:
|
|
206
|
+
|
|
207
|
+
[source,ruby]
|
|
208
|
+
----
|
|
209
|
+
# Exact match only
|
|
210
|
+
results = engine.search(
|
|
211
|
+
pattern: "action_schema.action",
|
|
212
|
+
exact: true
|
|
213
|
+
)
|
|
214
|
+
----
|
|
215
|
+
|
|
216
|
+
== Advanced search options
|
|
217
|
+
|
|
218
|
+
=== Filtering by element type
|
|
219
|
+
|
|
220
|
+
Limit search to specific element types:
|
|
221
|
+
|
|
222
|
+
[source,ruby]
|
|
223
|
+
----
|
|
224
|
+
# Search only entities
|
|
225
|
+
entities = engine.search(
|
|
226
|
+
pattern: "action",
|
|
227
|
+
type: "entity"
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Search only types
|
|
231
|
+
types = engine.search(
|
|
232
|
+
pattern: "status",
|
|
233
|
+
type: "type"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# Search only attributes
|
|
237
|
+
attributes = engine.search(
|
|
238
|
+
pattern: "id",
|
|
239
|
+
type: "attribute"
|
|
240
|
+
)
|
|
241
|
+
----
|
|
242
|
+
|
|
243
|
+
=== Combining filters
|
|
244
|
+
|
|
245
|
+
Use multiple filters together:
|
|
246
|
+
|
|
247
|
+
[source,ruby]
|
|
248
|
+
----
|
|
249
|
+
# Search SELECT types in specific schema
|
|
250
|
+
results = engine.search(
|
|
251
|
+
pattern: "*",
|
|
252
|
+
type: "type",
|
|
253
|
+
schema: "action_schema",
|
|
254
|
+
category: "select"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
# Search entities with pattern in specific schema
|
|
258
|
+
results = engine.search(
|
|
259
|
+
pattern: "action*",
|
|
260
|
+
type: "entity",
|
|
261
|
+
schema: "action_schema"
|
|
262
|
+
)
|
|
263
|
+
----
|
|
264
|
+
|
|
265
|
+
=== Case sensitivity
|
|
266
|
+
|
|
267
|
+
Control case-sensitive matching:
|
|
268
|
+
|
|
269
|
+
[source,ruby]
|
|
270
|
+
----
|
|
271
|
+
# Case-insensitive (default)
|
|
272
|
+
results = engine.search(pattern: "ACTION")
|
|
273
|
+
|
|
274
|
+
# Case-sensitive
|
|
275
|
+
results = engine.search(
|
|
276
|
+
pattern: "ACTION",
|
|
277
|
+
case_sensitive: true
|
|
278
|
+
)
|
|
279
|
+
----
|
|
280
|
+
|
|
281
|
+
=== Depth filtering
|
|
282
|
+
|
|
283
|
+
Limit search by path depth:
|
|
284
|
+
|
|
285
|
+
[source,ruby]
|
|
286
|
+
----
|
|
287
|
+
# Maximum depth 2 (schema.entity)
|
|
288
|
+
results = engine.search_with_depth(
|
|
289
|
+
pattern: "*",
|
|
290
|
+
max_depth: 2
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
# Maximum depth 3 (schema.entity.attribute)
|
|
294
|
+
results = engine.search_with_depth(
|
|
295
|
+
pattern: "action*",
|
|
296
|
+
max_depth: 3
|
|
297
|
+
)
|
|
298
|
+
----
|
|
299
|
+
|
|
300
|
+
=== Ranked search
|
|
301
|
+
|
|
302
|
+
Search with relevance scoring:
|
|
303
|
+
|
|
304
|
+
[source,ruby]
|
|
305
|
+
----
|
|
306
|
+
# Search with ranking
|
|
307
|
+
results = engine.search_ranked(
|
|
308
|
+
pattern: "action",
|
|
309
|
+
boost_exact: 10, # Boost for exact matches
|
|
310
|
+
boost_prefix: 5 # Boost for prefix matches
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Results include :relevance_score
|
|
314
|
+
results.each do |r|
|
|
315
|
+
puts "Score #{r[:relevance_score]}: #{r[:path]}"
|
|
316
|
+
end
|
|
317
|
+
----
|
|
318
|
+
|
|
319
|
+
=== Advanced combined search
|
|
320
|
+
|
|
321
|
+
Use all features together:
|
|
322
|
+
|
|
323
|
+
[source,ruby]
|
|
324
|
+
----
|
|
325
|
+
results = engine.search_advanced(
|
|
326
|
+
pattern: "action*",
|
|
327
|
+
type: "entity",
|
|
328
|
+
schema: "action_schema",
|
|
329
|
+
max_depth: 2,
|
|
330
|
+
ranked: true,
|
|
331
|
+
case_sensitive: false
|
|
332
|
+
)
|
|
333
|
+
----
|
|
334
|
+
|
|
335
|
+
== CLI query commands
|
|
336
|
+
|
|
337
|
+
=== Package list command
|
|
338
|
+
|
|
339
|
+
List elements from command line:
|
|
340
|
+
|
|
341
|
+
[source,bash]
|
|
342
|
+
----
|
|
343
|
+
# List all entities
|
|
344
|
+
expressir package list schemas.ler --type entity
|
|
345
|
+
|
|
346
|
+
# List all types
|
|
347
|
+
expressir package list schemas.ler --type type
|
|
348
|
+
|
|
349
|
+
# List SELECT types
|
|
350
|
+
expressir package list schemas.ler --type type --category select
|
|
351
|
+
|
|
352
|
+
# Filter by schema
|
|
353
|
+
expressir package list schemas.ler --type entity --schema action_schema
|
|
354
|
+
|
|
355
|
+
# Show only count
|
|
356
|
+
expressir package list schemas.ler --type entity --count-only
|
|
357
|
+
----
|
|
358
|
+
|
|
359
|
+
.Output formats
|
|
360
|
+
[example]
|
|
361
|
+
====
|
|
362
|
+
[source,bash]
|
|
363
|
+
----
|
|
364
|
+
# Text format (default)
|
|
365
|
+
expressir package list schemas.ler --type entity
|
|
366
|
+
|
|
367
|
+
# JSON format
|
|
368
|
+
expressir package list schemas.ler --type entity --format json
|
|
369
|
+
|
|
370
|
+
# YAML format
|
|
371
|
+
expressir package list schemas.ler --type entity --format yaml
|
|
372
|
+
----
|
|
373
|
+
====
|
|
374
|
+
|
|
375
|
+
=== Package search command
|
|
376
|
+
|
|
377
|
+
Search patterns from command line:
|
|
378
|
+
|
|
379
|
+
[source,bash]
|
|
380
|
+
----
|
|
381
|
+
# Simple search
|
|
382
|
+
expressir package search schemas.ler "action"
|
|
383
|
+
|
|
384
|
+
# With type filter
|
|
385
|
+
expressir package search schemas.ler "action" --type entity
|
|
386
|
+
|
|
387
|
+
# With schema filter
|
|
388
|
+
expressir package search schemas.ler "action" --schema action_schema
|
|
389
|
+
|
|
390
|
+
# Wildcard search
|
|
391
|
+
expressir package search schemas.ler "*.action"
|
|
392
|
+
|
|
393
|
+
# Prefix search
|
|
394
|
+
expressir package search schemas.ler "action*"
|
|
395
|
+
----
|
|
396
|
+
|
|
397
|
+
.Search options
|
|
398
|
+
[example]
|
|
399
|
+
====
|
|
400
|
+
[source,bash]
|
|
401
|
+
----
|
|
402
|
+
# Case-sensitive search
|
|
403
|
+
expressir package search schemas.ler "Action" --case-sensitive
|
|
404
|
+
|
|
405
|
+
# Regular expression search
|
|
406
|
+
expressir package search schemas.ler "action|approval" --regex
|
|
407
|
+
|
|
408
|
+
# Exact match only
|
|
409
|
+
expressir package search schemas.ler "action_schema.action" --exact
|
|
410
|
+
|
|
411
|
+
# With result limit
|
|
412
|
+
expressir package search schemas.ler "action" --limit 10
|
|
413
|
+
|
|
414
|
+
# Show only count
|
|
415
|
+
expressir package search schemas.ler "action" --count-only
|
|
416
|
+
----
|
|
417
|
+
====
|
|
418
|
+
|
|
419
|
+
=== Package tree command
|
|
420
|
+
|
|
421
|
+
Display hierarchical tree view:
|
|
422
|
+
|
|
423
|
+
[source,bash]
|
|
424
|
+
----
|
|
425
|
+
# Full tree
|
|
426
|
+
expressir package tree schemas.ler
|
|
427
|
+
|
|
428
|
+
# Limit depth
|
|
429
|
+
expressir package tree schemas.ler --depth 2
|
|
430
|
+
|
|
431
|
+
# Filter by schema
|
|
432
|
+
expressir package tree schemas.ler --schema action_schema
|
|
433
|
+
|
|
434
|
+
# Filter by type
|
|
435
|
+
expressir package tree schemas.ler --type entity
|
|
436
|
+
|
|
437
|
+
# Show element counts
|
|
438
|
+
expressir package tree schemas.ler --counts
|
|
439
|
+
|
|
440
|
+
# Disable colors
|
|
441
|
+
expressir package tree schemas.ler --no-color
|
|
442
|
+
----
|
|
443
|
+
|
|
444
|
+
.Example tree output
|
|
445
|
+
[example]
|
|
446
|
+
====
|
|
447
|
+
[source]
|
|
448
|
+
----
|
|
449
|
+
schemas.ler
|
|
450
|
+
├─ action_schema (schema) [15 entities, 8 types, 2 functions]
|
|
451
|
+
│ ├─ action (entity)
|
|
452
|
+
│ │ ├─ id (attribute): STRING
|
|
453
|
+
│ │ ├─ name (attribute): STRING
|
|
454
|
+
│ │ └─ description (attribute): STRING
|
|
455
|
+
│ ├─ action_directive (entity)
|
|
456
|
+
│ │ ├─ id (attribute): STRING
|
|
457
|
+
│ │ └─ directive (attribute): action_directive_type
|
|
458
|
+
│ ├─ action_status (type)
|
|
459
|
+
│ │ ├─ pending
|
|
460
|
+
│ │ ├─ in_progress
|
|
461
|
+
│ │ └─ completed
|
|
462
|
+
│ └─ action_directive_type (type)
|
|
463
|
+
└─ approval_schema (schema) [8 entities, 5 types]
|
|
464
|
+
├─ approval (entity)
|
|
465
|
+
└─ approval_status (type)
|
|
466
|
+
----
|
|
467
|
+
====
|
|
468
|
+
|
|
469
|
+
== Common query patterns
|
|
470
|
+
|
|
471
|
+
=== Find specific entity
|
|
472
|
+
|
|
473
|
+
[source,ruby]
|
|
474
|
+
----
|
|
475
|
+
# Using repository index directly (fastest)
|
|
476
|
+
entity = repo.find_entity(qualified_name: "action_schema.action")
|
|
477
|
+
|
|
478
|
+
if entity
|
|
479
|
+
puts "Found: #{entity.id}"
|
|
480
|
+
puts "Schema: #{entity.parent.id}"
|
|
481
|
+
puts "Path: #{entity.path}"
|
|
482
|
+
end
|
|
483
|
+
----
|
|
484
|
+
|
|
485
|
+
=== List entities from schema
|
|
486
|
+
|
|
487
|
+
[source,ruby]
|
|
488
|
+
----
|
|
489
|
+
# Using repository
|
|
490
|
+
entities = repo.list_entities(schema: "action_schema", format: :hash)
|
|
491
|
+
|
|
492
|
+
entities.each do |e|
|
|
493
|
+
puts "#{e[:schema]}.#{e[:id]}"
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
# Using search engine
|
|
497
|
+
entities = engine.list(type: "entity", schema: "action_schema")
|
|
498
|
+
----
|
|
499
|
+
|
|
500
|
+
=== Find types by category
|
|
501
|
+
|
|
502
|
+
[source,ruby]
|
|
503
|
+
----
|
|
504
|
+
# SELECT types
|
|
505
|
+
select_types = repo.list_types(category: "select", format: :hash)
|
|
506
|
+
|
|
507
|
+
select_types.each do |t|
|
|
508
|
+
puts "#{t[:schema]}.#{t[:id]} [#{t[:category]}]"
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
# ENUMERATION types
|
|
512
|
+
enum_types = repo.list_types(category: "enumeration", format: :hash)
|
|
513
|
+
----
|
|
514
|
+
|
|
515
|
+
=== Search across all schemas
|
|
516
|
+
|
|
517
|
+
[source,ruby]
|
|
518
|
+
----
|
|
519
|
+
# Find all entities named "action"
|
|
520
|
+
results = engine.search(pattern: "action", type: "entity")
|
|
521
|
+
|
|
522
|
+
results.each do |r|
|
|
523
|
+
puts "Found in #{r[:schema]}: #{r[:id]}"
|
|
524
|
+
end
|
|
525
|
+
----
|
|
526
|
+
|
|
527
|
+
=== Find all attributes with specific name
|
|
528
|
+
|
|
529
|
+
[source,ruby]
|
|
530
|
+
----
|
|
531
|
+
# Find all "id" attributes
|
|
532
|
+
results = engine.search(pattern: "*.*.id", type: "attribute")
|
|
533
|
+
|
|
534
|
+
results.each do |r|
|
|
535
|
+
puts "Attribute: #{r[:path]}"
|
|
536
|
+
end
|
|
537
|
+
----
|
|
538
|
+
|
|
539
|
+
=== Count elements by type
|
|
540
|
+
|
|
541
|
+
[source,ruby]
|
|
542
|
+
----
|
|
543
|
+
# Count all entities
|
|
544
|
+
entity_count = engine.count(type: "entity")
|
|
545
|
+
puts "Total entities: #{entity_count}"
|
|
546
|
+
|
|
547
|
+
# Count entities in specific schema
|
|
548
|
+
schema_entities = engine.count(
|
|
549
|
+
type: "entity",
|
|
550
|
+
schema: "action_schema"
|
|
551
|
+
)
|
|
552
|
+
puts "Entities in action_schema: #{schema_entities}"
|
|
553
|
+
|
|
554
|
+
# Count SELECT types
|
|
555
|
+
select_count = engine.count(
|
|
556
|
+
type: "type",
|
|
557
|
+
category: "select"
|
|
558
|
+
)
|
|
559
|
+
puts "SELECT types: #{select_count}"
|
|
560
|
+
----
|
|
561
|
+
|
|
562
|
+
== Performance optimization
|
|
563
|
+
|
|
564
|
+
=== Use pre-built indexes
|
|
565
|
+
|
|
566
|
+
Indexes are automatically loaded from packages:
|
|
567
|
+
|
|
568
|
+
[source,ruby]
|
|
569
|
+
----
|
|
570
|
+
repo = Expressir::Model::Repository.from_package("schemas.ler")
|
|
571
|
+
|
|
572
|
+
# Indexes already loaded - no build needed
|
|
573
|
+
entity = repo.find_entity(qualified_name: "action_schema.action")
|
|
574
|
+
----
|
|
575
|
+
|
|
576
|
+
Performance comparison:
|
|
577
|
+
|
|
578
|
+
[source]
|
|
579
|
+
----
|
|
580
|
+
Without indexes: ~500ms to find entity
|
|
581
|
+
With pre-built indexes: ~2ms to find entity
|
|
582
|
+
Speed improvement: 250x faster
|
|
583
|
+
----
|
|
584
|
+
|
|
585
|
+
=== Prefer specific queries
|
|
586
|
+
|
|
587
|
+
More specific searches are faster:
|
|
588
|
+
|
|
589
|
+
[source,ruby]
|
|
590
|
+
----
|
|
591
|
+
# Slower: Search all types
|
|
592
|
+
all_results = engine.search(pattern: "action")
|
|
593
|
+
|
|
594
|
+
# Faster: Search specific type
|
|
595
|
+
entities_only = engine.search(
|
|
596
|
+
pattern: "action",
|
|
597
|
+
type: "entity"
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
# Fastest: Direct repository lookup
|
|
601
|
+
entity = repo.find_entity(
|
|
602
|
+
qualified_name: "action_schema.action"
|
|
603
|
+
)
|
|
604
|
+
----
|
|
605
|
+
|
|
606
|
+
=== Cache search results
|
|
607
|
+
|
|
608
|
+
Cache frequently used queries:
|
|
609
|
+
|
|
610
|
+
[source,ruby]
|
|
611
|
+
----
|
|
612
|
+
class QueryCache
|
|
613
|
+
def initialize(engine)
|
|
614
|
+
@engine = engine
|
|
615
|
+
@cache = {}
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
def search(pattern:, **options)
|
|
619
|
+
cache_key = [pattern, options].hash
|
|
620
|
+
@cache[cache_key] ||= @engine.search(
|
|
621
|
+
pattern: pattern,
|
|
622
|
+
**options
|
|
623
|
+
)
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
def clear
|
|
627
|
+
@cache.clear
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
# Usage
|
|
632
|
+
cache = QueryCache.new(engine)
|
|
633
|
+
results = cache.search(pattern: "action", type: "entity")
|
|
634
|
+
----
|
|
635
|
+
|
|
636
|
+
=== Limit result sets
|
|
637
|
+
|
|
638
|
+
Use limits for large result sets:
|
|
639
|
+
|
|
640
|
+
[source,bash]
|
|
641
|
+
----
|
|
642
|
+
# CLI with limit
|
|
643
|
+
expressir package search schemas.ler "action" --limit 10
|
|
644
|
+
|
|
645
|
+
# Or get count first
|
|
646
|
+
expressir package search schemas.ler "action" --count-only
|
|
647
|
+
----
|
|
648
|
+
|
|
649
|
+
== Result formatting
|
|
650
|
+
|
|
651
|
+
=== Hash format
|
|
652
|
+
|
|
653
|
+
Default format for programmatic use:
|
|
654
|
+
|
|
655
|
+
[source,ruby]
|
|
656
|
+
----
|
|
657
|
+
results = engine.search(pattern: "action")
|
|
658
|
+
|
|
659
|
+
# Each result is a hash:
|
|
660
|
+
# {
|
|
661
|
+
# id: "action",
|
|
662
|
+
# type: "entity",
|
|
663
|
+
# schema: "action_schema",
|
|
664
|
+
# path: "action_schema.action"
|
|
665
|
+
# }
|
|
666
|
+
|
|
667
|
+
results.each do |r|
|
|
668
|
+
puts "#{r[:type]}: #{r[:schema]}.#{r[:id]}"
|
|
669
|
+
end
|
|
670
|
+
----
|
|
671
|
+
|
|
672
|
+
=== JSON format
|
|
673
|
+
|
|
674
|
+
Convert to JSON for export:
|
|
675
|
+
|
|
676
|
+
[source,ruby]
|
|
677
|
+
----
|
|
678
|
+
require "json"
|
|
679
|
+
|
|
680
|
+
results = engine.search(pattern: "action")
|
|
681
|
+
json = JSON.pretty_generate(results)
|
|
682
|
+
File.write("results.json", json)
|
|
683
|
+
----
|
|
684
|
+
|
|
685
|
+
Or from CLI:
|
|
686
|
+
|
|
687
|
+
[source,bash]
|
|
688
|
+
----
|
|
689
|
+
expressir package search schemas.ler "action" --format json > results.json
|
|
690
|
+
----
|
|
691
|
+
|
|
692
|
+
=== YAML format
|
|
693
|
+
|
|
694
|
+
Convert to YAML:
|
|
695
|
+
|
|
696
|
+
[source,ruby]
|
|
697
|
+
----
|
|
698
|
+
require "yaml"
|
|
699
|
+
|
|
700
|
+
results = engine.search(pattern: "action")
|
|
701
|
+
yaml = results.to_yaml
|
|
702
|
+
File.write("results.yaml", yaml)
|
|
703
|
+
----
|
|
704
|
+
|
|
705
|
+
Or from CLI:
|
|
706
|
+
|
|
707
|
+
[source,bash]
|
|
708
|
+
----
|
|
709
|
+
expressir package search schemas.ler "action" --format yaml > results.yaml
|
|
710
|
+
----
|
|
711
|
+
|
|
712
|
+
=== Custom formatting
|
|
713
|
+
|
|
714
|
+
Create custom output format:
|
|
715
|
+
|
|
716
|
+
[source,ruby]
|
|
717
|
+
----
|
|
718
|
+
def format_results(results)
|
|
719
|
+
results.map do |r|
|
|
720
|
+
{
|
|
721
|
+
full_name: "#{r[:schema]}.#{r[:id]}",
|
|
722
|
+
type: r[:type],
|
|
723
|
+
category: r[:category]
|
|
724
|
+
}.compact
|
|
725
|
+
end
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
results = engine.search(pattern: "action")
|
|
729
|
+
formatted = format_results(results)
|
|
730
|
+
----
|
|
731
|
+
|
|
732
|
+
== Working with query results
|
|
733
|
+
|
|
734
|
+
=== Accessing result data
|
|
735
|
+
|
|
736
|
+
Extract information from results:
|
|
737
|
+
|
|
738
|
+
[source,ruby]
|
|
739
|
+
----
|
|
740
|
+
results = engine.search(pattern: "action", type: "entity")
|
|
741
|
+
|
|
742
|
+
# Get just the IDs
|
|
743
|
+
ids = results.map { |r| r[:id] }
|
|
744
|
+
puts "IDs: #{ids.join(', ')}"
|
|
745
|
+
|
|
746
|
+
# Get qualified names
|
|
747
|
+
qualified_names = results.map { |r| "#{r[:schema]}.#{r[:id]}" }
|
|
748
|
+
puts "Qualified names: #{qualified_names.join(', ')}"
|
|
749
|
+
|
|
750
|
+
# Group by schema
|
|
751
|
+
by_schema = results.group_by { |r| r[:schema] }
|
|
752
|
+
by_schema.each do |schema, items|
|
|
753
|
+
puts "#{schema}: #{items.size} items"
|
|
754
|
+
end
|
|
755
|
+
----
|
|
756
|
+
|
|
757
|
+
=== Filtering results
|
|
758
|
+
|
|
759
|
+
Apply additional filters to results:
|
|
760
|
+
|
|
761
|
+
[source,ruby]
|
|
762
|
+
----
|
|
763
|
+
results = engine.search(pattern: "action")
|
|
764
|
+
|
|
765
|
+
# Filter by type
|
|
766
|
+
entities = results.select { |r| r[:type] == "entity" }
|
|
767
|
+
|
|
768
|
+
# Filter by schema
|
|
769
|
+
action_schema = results.select { |r| r[:schema] == "action_schema" }
|
|
770
|
+
|
|
771
|
+
# Filter by path depth
|
|
772
|
+
shallow = results.select { |r| r[:path].split(".").size <= 2 }
|
|
773
|
+
----
|
|
774
|
+
|
|
775
|
+
=== Sorting results
|
|
776
|
+
|
|
777
|
+
Sort results by different criteria:
|
|
778
|
+
|
|
779
|
+
[source,ruby]
|
|
780
|
+
----
|
|
781
|
+
results = engine.search(pattern: "action")
|
|
782
|
+
|
|
783
|
+
# Sort by ID
|
|
784
|
+
by_id = results.sort_by { |r| r[:id] }
|
|
785
|
+
|
|
786
|
+
# Sort by schema
|
|
787
|
+
by_schema = results.sort_by { |r| [r[:schema], r[:id]] }
|
|
788
|
+
|
|
789
|
+
# Sort by type
|
|
790
|
+
by_type = results.sort_by { |r| [r[:type], r[:id]] }
|
|
791
|
+
|
|
792
|
+
# Sort by path depth (shortest first)
|
|
793
|
+
by_depth = results.sort_by { |r| r[:path].split(".").size }
|
|
794
|
+
----
|
|
795
|
+
|
|
796
|
+
== Next steps
|
|
797
|
+
|
|
798
|
+
* link:validating-packages.html[Validating Packages] - Verify package integrity
|
|
799
|
+
* link:package-formats.html[Package Formats] - Understanding serialization formats
|
|
800
|
+
* link:../ruby-api/search-engine.html[Search Engine API] - Detailed API reference
|
|
801
|
+
* link:loading-packages.html[Loading Packages] - Package loading guide
|
|
802
|
+
|
|
803
|
+
== Summary
|
|
804
|
+
|
|
805
|
+
Key takeaways for querying LER packages:
|
|
806
|
+
|
|
807
|
+
* SearchEngine provides powerful pattern matching
|
|
808
|
+
* Pre-built indexes enable fast lookups
|
|
809
|
+
* Support for wildcards, regex, and exact matching
|
|
810
|
+
* Filter by type, schema, and category
|
|
811
|
+
* CLI commands for interactive queries
|
|
812
|
+
* Multiple output formats (text, JSON, YAML)
|
|
813
|
+
* Tree view for hierarchical visualization
|
|
814
|
+
* Rank results by relevance
|
|
815
|
+
* Depth filtering for focused results
|
|
816
|
+
|
|
817
|
+
Best practices:
|
|
818
|
+
|
|
819
|
+
* Use direct repository lookups for known qualified names
|
|
820
|
+
* Leverage pre-built indexes for performance
|
|
821
|
+
* Filter early to reduce result sets
|
|
822
|
+
* Cache frequently used queries
|
|
823
|
+
* Use specific type filters when possible
|
|
824
|
+
* Limit results for large queries
|
|
825
|
+
* Choose appropriate output format for use case
|
|
826
|
+
* Combine filters for precise results
|