Entity Identifier Resolver (EIR) is a local, strongly typed entity database and search engine written in Rust.
It is designed for applications that need to find an entity from names, metadata, or relationships rather than from a single known identifier.
EIR is under active development. The CLI, storage, and search systems are functional and tested. The server is currently a CLI placeholder.
β οΈ Warning: EIR is not encrypted. Do not use it to store sensitive data.
An EIR database contains entities identified by an EntityID.
An entity can have several aliases, tags, sources, attributes, and relationships:
{
"id": 1001,
"aliases": [
"FizzBerry Spark",
"FizzBerry",
"Berry Spark"
],
"tags": [
"drink",
"berry"
],
"sources": [
{
"provider": "Open Food Facts",
"verified": true
}
],
"attributes": [],
"relationships": []
}Aliases are names that can be used to find an entity.
For example, the same entity might be known as:
FizzBerry Spark
FizzBerry
Berry Spark
EIR can search aliases using exact, prefix, and fuzzy matching.
Tags provide categories or other labels associated with an entity.
FizzBerry Spark
βββ drink
βββ berry
Tags can also participate in searches.
Sources record where information about an entity came from.
An entity can have information from several providers, and source information can be used during search and inspection.
Attributes describe properties of an entity.
For example:
brand = FizzBerry
category = Soft Drink
country = Denmark
Unlike an alias, an attribute describes the entity rather than providing another name for it.
Relationships connect one entity to another.
For example:
FizzBerry Spark
β
βββ manufactured_by ββ> FizzBerry Foods
This allows EIR to use information about related entities when resolving a query.
EIR does not use one search algorithm for every query.
A query can be handled by several search operations:
flowchart LR
QUERY["Query"] --> PLANNER["Planner"]
PLANNER --> EXACT["Exact Alias"]
PLANNER --> PREFIX["Prefix Alias"]
PLANNER --> FUZZY["Fuzzy Alias"]
PLANNER --> TOKEN["Token"]
PLANNER --> TAG["Tag"]
PLANNER --> PROPERTY["Property"]
PLANNER --> RELATIONSHIP["Relationship"]
EXACT --> CANDIDATES["Candidates"]
PREFIX --> CANDIDATES
FUZZY --> CANDIDATES
TOKEN --> CANDIDATES
TAG --> CANDIDATES
PROPERTY --> CANDIDATES
RELATIONSHIP --> CANDIDATES
CANDIDATES --> RANKER["Ranker"]
RANKER --> RESULTS["Results"]
The search system records which operations produced each candidate. This makes it possible to see why an entity matched a query.
For example, a result might have matched through:
ExactAlias
Token
Tag
rather than simply returning a score with no explanation.
The database contains the entities and the structures needed to search them.
Database
βββ Entities
βββ Tag Registry
βββ Source Registry
βββ Attribute-Key Registry
βββ Relationship-Type Registry
βββ Indexes
Registries assign internal identifiers to repeated values such as tags, source names, attribute keys, and relationship types.
Indexes provide the structures used to find entities efficiently.
The indexes are built from the current database contents and include structures for aliases, prefixes, fuzzy matching, tokens, tags, sources, attributes, and relationships.
The logical database is stored using persistent storage managed by the EIR engine.
A database has a layout similar to:
database/
βββ database.eir
βββ eir.toml
βββ segments/
βββ wal/
The storage backend uses DEIR segments and a write-ahead log.
The WAL records database mutations so they can be recovered if necessary.
Compaction can later rewrite the stored data to remove obsolete storage.
The main runtime object is Engine.
flowchart TB
CLI["eir-cli"]
ENGINE["Engine"]
DATABASE["Database"]
RESOLVER["Resolver"]
BACKEND["Backend"]
QUERY["Query"]
SEARCH["Search"]
INDEXES["Indexes"]
WAL["WAL"]
SEGMENTS["DEIR Segments"]
CLI --> ENGINE
ENGINE --> DATABASE
ENGINE --> RESOLVER
ENGINE --> BACKEND
RESOLVER --> QUERY
QUERY --> SEARCH
SEARCH --> INDEXES
BACKEND --> WAL
BACKEND --> SEGMENTS
DATABASE --> INDEXES
Engine coordinates the database, resolver, and storage backend.
The database contains the entity data and indexes, while the resolver uses those indexes to perform searches.
flowchart TB
USER["Application / CLI"]
ENGINE["Engine"]
DATABASE["Database"]
ENTITIES["Entity Documents"]
REGISTRIES["Registries"]
INDEXES["Search Indexes"]
QUERY["Query"]
PLANNER["Planner"]
EXECUTOR["Executor"]
RANKER["Ranker"]
RESULTS["Search Results"]
STORAGE["Storage Backend"]
WAL["Write-Ahead Log"]
SEGMENTS["DEIR Segments"]
USER --> ENGINE
ENGINE --> DATABASE
ENGINE --> STORAGE
DATABASE --> ENTITIES
DATABASE --> REGISTRIES
DATABASE --> INDEXES
ENGINE --> QUERY
QUERY --> PLANNER
PLANNER --> EXECUTOR
EXECUTOR --> INDEXES
EXECUTOR --> RANKER
RANKER --> RESULTS
STORAGE --> WAL
STORAGE --> SEGMENTS
This is the overall flow:
Entity data
β
βΌ
Database
β
βββ Registries
βββ Search indexes
β
βΌ
Resolver
β
βΌ
Query
β
βΌ
Results
The eir CLI provides tools for working with databases.
Current commands include:
init
build
stats
inspect
search
insert
remove
update
compact
merge
server
completions
For example:
cargo eir init data nutrition
cargo eir build \
--input entities.json \
--database data/nutrition
cargo eir search \
data/nutrition/nutrition.eir \
"FizzBerry"See docs/cli.md for the complete command reference.
EntityIdentifierResolver/
βββ crates/
β βββ eir-core/
β βββ eir-cli/
β βββ eir-version/
βββ apps/
βββ docs/
βββ fixtures/
The core database and search engine.
It contains the entity model, engine, storage, indexing, query, and search systems.
The command-line interface built on top of eir-core.
Version-related functionality used by the database and merge system.
Clone the repository:
git clone https://github.com/HandsOnDigits/EntityIdentifierResolver.git
cd EntityIdentifierResolverCheck the workspace:
cargo check --workspaceRun the tests:
cargo test --workspaceFormat the code:
cargo fmt --alldocs/cli.mdβ CLI commands and database operationsdocs/model.mdβ entity model reference
See LICENSE for the license.
EIR is designed around a few simple principles:
- Local β no remote service required
- Structured β entities contain more than just names
- Fast β specialized indexes for different search operations
- Explainable β search results expose matching signals
- Embeddable β the core engine is independent of the CLI
- Recoverable β persistent storage uses snapshots and WAL
- Rust workspace
-
eir-corecrate -
eir-clicrate -
eir-versioncrate - Entity model
-
EntityID -
EntityType - Entity aliases
- Tags
- Sources
- Attributes
- Relationships
- Registries / interners
- Database abstraction
- Engine abstraction
- Resolver abstraction
- Stabilize public core API
- Document core architecture
- Define database compatibility/versioning policy
- Improve error model
- Exact alias search
- Prefix alias search
- Fuzzy alias search
- Token search
- Tag search
- Attribute/property search
- Relationship search
- Alias index
- Prefix trie
- Fuzzy/BK-tree index
- Token inverted index
- Posting lists
- Query parser
- Query intent
- Query filters
- Search planner
- Search executor
- Search stages
- Candidate collection
- Search signals
- Ranking
- Search explanations
- Search tests
- Improve ranking quality
- Tune fuzzy matching
- Add more query operators
- Improve relationship queries
- Improve search explanations
- Benchmark search performance
- Test against larger real-world datasets
- Add configurable ranking strategies
- Database lifecycle
- Database creation
- Database opening
-
.eirdatabase identity -
eir.tomlconfiguration - Storage configuration
- DEIR storage format
- Storage segments
- Segment manager
- Backend abstraction
- Write-ahead log (WAL)
- WAL replay
- Database recovery
- Snapshot persistence
- Flush
- Index rebuilding
- Database statistics
- Insert entities
- Remove entities
- Update entities
- Duplicate entity detection
- Entity validation
- Index rebuild after mutation
- WAL support for insert
- WAL support for remove
- WAL support for update
- Mutation recovery tests
- Compact command
- Segment rewrite
- Remove obsolete storage data
- Report storage size before/after
- Report reclaimed space
- Compaction tests
- Add automatic compaction policy
- Add configurable compaction thresholds
- Merge command
- Merge two databases
- Duplicate entity ID detection
- Reject output/input collisions
- Combine entity collections
- Rebuild merged indexes
- Merge tests
- Support merging more than two databases
- Improve merge performance
- Add merge conflict strategies
- Document registry remapping
- Add large-database merge benchmarks
- CLI with Clap
-
init -
build -
stats -
inspect -
search -
insert -
remove -
update -
compact -
merge -
servercommand structure - Shell completions
- CLI integration tests
- Database lifecycle tests
- Finish server implementation
- Improve CLI output formatting
- Add machine-readable output
- Improve error messages
- Improve command help
- Add CLI benchmarks
- Add support for CSV file import
- Server command scaffold
- Server lifecycle command structure
- HTTP API
- Search endpoint
- Entity lookup endpoint
- Entity insertion endpoint
- Entity update endpoint
- Entity removal endpoint
- Database statistics endpoint
- Health endpoint
- API documentation
- Authentication strategy
- Request validation
- API integration tests
- JSON entity fixtures
- Test entities
- Test sources
- Test tags
- Test attributes
- Test relationships
- Larger test database
- CLI lifecycle fixture tests
- CSV entity fixtures
- Unit tests
- Database lifecycle tests
- Persistence tests
- WAL recovery tests
- Insert tests
- Remove tests
- Update tests
- Compaction tests
- Merge tests
- Search tests
- Query tests
- CLI tests
- Duplicate ID tests
- Output/input collision tests
- Large dataset tests
- Performance benchmarks
- Search relevance benchmarks
- Storage benchmarks
- Fuzz testing
- Crash/recovery testing
- Concurrency testing
- CLI documentation
- Architecture documentation
- Search architecture documentation
- Storage documentation
- Mermaid architecture diagrams
- README architecture overview
- Keep README aligned with source
- Keep CLI docs aligned with commands
- Database format documentation
- Entity schema documentation
- Search/query documentation
- Storage format specification
- API documentation
- Contributor guide
- Architecture decision records
- Benchmark database creation
- Benchmark inserts
- Benchmark updates
- Benchmark deletes
- Benchmark search
- Benchmark fuzzy search
- Benchmark index building
- Benchmark database opening
- Benchmark WAL replay
- Benchmark compaction
- Benchmark merge
- Memory usage profiling
- Large-dataset testing
- Investigate GPU acceleration
- Local-first architecture
- No search history by default
- No external service required for core search
- No telemetry in the core engine
- Document security model
- Document filesystem permissions
- Optional database encryption strategy
- API authentication
- API authorization
- Security audit
- Entity model
- Database
- Storage
- Indexing
- Resolver
- Search
- Persistence
- WAL
- Recovery
- Insert
- Update
- Remove
- Compaction
- Merge
- Database creation
- Build
- Search
- Inspect
- Stats
- Mutations
- Maintenance commands
- Performance benchmarks
- Large dataset testing
- Complete documentation
- Stable public API
- Error handling review
- Recovery testing
- HTTP server
- API
- TypeScript client
See the repository for the current license.
The documentation was created with the help of AI, but otherwise, all the code was written by humans.