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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +98 -0
  3. data/.github/workflows/links.yml +100 -0
  4. data/.github/workflows/rake.yml +4 -0
  5. data/.github/workflows/release.yml +5 -0
  6. data/.github/workflows/validate_schemas.yml +1 -1
  7. data/.gitignore +3 -0
  8. data/.rubocop.yml +1 -1
  9. data/.rubocop_todo.yml +244 -39
  10. data/Gemfile +2 -1
  11. data/README.adoc +621 -54
  12. data/docs/Gemfile +12 -0
  13. data/docs/_config.yml +141 -0
  14. data/docs/_guides/changes/changes-format.adoc +778 -0
  15. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  16. data/docs/_guides/changes/index.adoc +396 -0
  17. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  18. data/docs/_guides/changes/validating-changes.adoc +681 -0
  19. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  20. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  21. data/docs/_guides/cli/format-schemas.adoc +547 -0
  22. data/docs/_guides/cli/index.adoc +8 -0
  23. data/docs/_guides/cli/managing-changes.adoc +927 -0
  24. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  25. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  26. data/docs/_guides/index.adoc +165 -0
  27. data/docs/_guides/ler/creating-packages.adoc +664 -0
  28. data/docs/_guides/ler/index.adoc +305 -0
  29. data/docs/_guides/ler/loading-packages.adoc +707 -0
  30. data/docs/_guides/ler/package-formats.adoc +748 -0
  31. data/docs/_guides/ler/querying-packages.adoc +826 -0
  32. data/docs/_guides/ler/validating-packages.adoc +750 -0
  33. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  34. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  35. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  36. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  37. data/docs/_guides/liquid/index.adoc +468 -0
  38. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  39. data/docs/_guides/manifests/index.adoc +307 -0
  40. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  41. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  42. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  43. data/docs/_guides/ruby-api/index.adoc +257 -0
  44. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  45. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  46. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  47. data/docs/_pages/data-model.adoc +665 -0
  48. data/docs/_pages/express-language.adoc +506 -0
  49. data/docs/_pages/getting-started.adoc +414 -0
  50. data/docs/_pages/index.adoc +116 -0
  51. data/docs/_pages/introduction.adoc +256 -0
  52. data/docs/_pages/ler-packages.adoc +837 -0
  53. data/docs/_pages/parsers.adoc +683 -0
  54. data/docs/_pages/schema-manifests.adoc +431 -0
  55. data/docs/_references/index.adoc +228 -0
  56. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  57. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  58. data/docs/_tutorials/index.adoc +221 -0
  59. data/docs/_tutorials/liquid-templates.adoc +806 -0
  60. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  61. data/docs/_tutorials/querying-schemas.adoc +751 -0
  62. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  63. data/docs/index.adoc +242 -0
  64. data/docs/lychee.toml +84 -0
  65. data/examples/demo_ler_usage.sh +86 -0
  66. data/examples/ler/README.md +111 -0
  67. data/examples/ler/simple_example.ler +0 -0
  68. data/examples/ler/simple_schema.exp +33 -0
  69. data/examples/ler_build.rb +75 -0
  70. data/examples/ler_cli.rb +79 -0
  71. data/examples/ler_demo_complete.rb +276 -0
  72. data/examples/ler_query.rb +91 -0
  73. data/examples/ler_query_examples.rb +305 -0
  74. data/examples/ler_stats.rb +81 -0
  75. data/examples/phase3_demo.rb +159 -0
  76. data/examples/query_demo_simple.rb +131 -0
  77. data/expressir.gemspec +2 -0
  78. data/lib/expressir/cli.rb +12 -4
  79. data/lib/expressir/commands/manifest.rb +427 -0
  80. data/lib/expressir/commands/package.rb +1274 -0
  81. data/lib/expressir/commands/validate.rb +70 -37
  82. data/lib/expressir/commands/validate_ascii.rb +607 -0
  83. data/lib/expressir/commands/validate_load.rb +88 -0
  84. data/lib/expressir/express/formatter.rb +5 -1
  85. data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
  86. data/lib/expressir/express/parser.rb +33 -0
  87. data/lib/expressir/manifest/resolver.rb +213 -0
  88. data/lib/expressir/manifest/validator.rb +195 -0
  89. data/lib/expressir/model/declarations/entity.rb +6 -0
  90. data/lib/expressir/model/dependency_resolver.rb +270 -0
  91. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  92. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  93. data/lib/expressir/model/indexes/type_index.rb +149 -0
  94. data/lib/expressir/model/interface_validator.rb +384 -0
  95. data/lib/expressir/model/repository.rb +400 -5
  96. data/lib/expressir/model/repository_validator.rb +295 -0
  97. data/lib/expressir/model/search_engine.rb +525 -0
  98. data/lib/expressir/model.rb +4 -94
  99. data/lib/expressir/package/builder.rb +200 -0
  100. data/lib/expressir/package/metadata.rb +81 -0
  101. data/lib/expressir/package/reader.rb +165 -0
  102. data/lib/expressir/schema_manifest.rb +11 -1
  103. data/lib/expressir/version.rb +1 -1
  104. data/lib/expressir.rb +15 -2
  105. metadata +114 -4
  106. data/docs/benchmarking.adoc +0 -107
  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