{"id":50476249,"url":"https://github.com/illuin-tech/poly-index","last_synced_at":"2026-06-01T13:31:03.857Z","repository":{"id":340780136,"uuid":"1167460292","full_name":"illuin-tech/poly-index","owner":"illuin-tech","description":"Simple java in-memory store with multiple/combined indexes","archived":false,"fork":false,"pushed_at":"2026-03-18T15:27:36.000Z","size":63,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-19T01:40:30.771Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/illuin-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-26T10:14:05.000Z","updated_at":"2026-03-18T10:31:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/illuin-tech/poly-index","commit_stats":null,"previous_names":["illuin-tech/poly-index"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/illuin-tech/poly-index","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuin-tech%2Fpoly-index","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuin-tech%2Fpoly-index/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuin-tech%2Fpoly-index/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuin-tech%2Fpoly-index/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/illuin-tech","download_url":"https://codeload.github.com/illuin-tech/poly-index/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuin-tech%2Fpoly-index/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33777967,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-01T13:31:03.020Z","updated_at":"2026-06-01T13:31:03.851Z","avatar_url":"https://github.com/illuin-tech.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PolyIndex\n\n[![Maven Build](https://github.com/illuin-tech/poly-index/actions/workflows/maven-build.yml/badge.svg?branch=master)](https://github.com/illuin/poly-index/actions/workflows/maven-build.yml)\n[![Maven Central Version](https://img.shields.io/maven-central/v/tech.illuin/poly-index)](https://central.sonatype.com/artifact/tech.illuin/poly-index)\n[![javadoc](https://javadoc.io/badge2/tech.illuin/poly-index/javadoc.svg)](https://javadoc.io/doc/tech.illuin/poly-index)\n[![codecov](https://codecov.io/gh/illuin-tech/poly-index/graph/badge.svg?token=LomQShlUZJ)](https://codecov.io/gh/illuin-tech/poly-index)\n![GitHub](https://img.shields.io/github/license/illuin-tech/poly-index)\n\nThe `poly-index` library is a lightweight Java utility providing simple in-memory indexing for objects, with multi-index lookup capabilities. It is basically a wrapper around standard java maps, but also allows Lucene-based in-memory indices. This allows the retrieval of objects using various indexing keys without manually managing multiple maps.\n\nUser interaction is straightforward: you \"push\" objects into the store where they are automatically indexed according to predefined keys. You can then retrieve them by querying the store with a specific key and a matching value, or even a list of keys to implement fallback or priority-based lookup logic.\n\n## I. Installation\n\nAdd the following in your `pom.xml`:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003etech.illuin\u003c/groupId\u003e\n    \u003cartifactId\u003epoly-index\u003c/artifactId\u003e\n    \u003cversion\u003e0.10\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## II. Quick API Overview\n\nSimple example: exact match\n\n```java\n// Define a key based on a field\nKey\u003cUser\u003e EMAIL_KEY = Key.of(User::email);\n\n// Initialize store and push data\nIndexedStore\u003cUser\u003e store = new MapStore\u003c\u003e(Index.of(EMAIL_KEY));\nstore.push(new User(\"john.doe@example.com\", \"John Doe\"));\n\n// Retrieve by value\nOptional\u003cUser\u003e user = store.getFirst(\"john.doe@example.com\", EMAIL_KEY);\n```\n\nMore complex example: priority matching with multiple keys\n\n```java\n// Define multiple keys (exact match and combination)\nKey\u003cVehicle\u003e PLATE_KEY = Key.of(Vehicle::plate);\nKey\u003cVehicle\u003e BRAND_MODEL_KEY = MapCombinationKey.of(\n    MapCombinationKey.requires(Vehicle::brand, Vehicle::model),\n    MapIndexType.FIRST\n);\n\nIndexedStore\u003cVehicle\u003e store = new MapStore\u003c\u003e(Index.of(PLATE_KEY, BRAND_MODEL_KEY));\nstore.pushAll(vehicles);\n\n// Query using the \"exemplar pattern\" ; try each key in order until a match is found\nVehicle search = new Vehicle(\"ABC-123\", \"Toyota\", \"Corolla\");\nOptional\u003cVehicle\u003e match = store.getFirstMatch(search, List.of(PLATE_KEY, BRAND_MODEL_KEY));\n```\n\n## III. Workflow\n\nThe general workflow when using `poly-index` is as follows:\n\n1. **Define index keys**: specify how identifiers are extracted from your objects\n  * Use `Key.of(Function)` for simple field matching.\n  * Use `MapCombinationKey.of(...)` for composite keys (multiple fields).\n2. **Initialize the store**: Create an `IndexedStore` by providing it with an `Index` registry containing all the keys you intend to use.\n3. **Populate the store**: Use `push(T)` or `pushAll(Collection\u003cT\u003e)` to add objects. They will be automatically indexed across all registered keys.\n4. **Query the store**:\n * `get(value, key)`: returns all matches for a given key and value.\n * `getFirst(value, key)`: returns the first match for a given key and value.\n * `getFirstMatch(exemplar, keys)`: (exemplar pattern) takes a template object and a list of keys, trying each key in order.\n\n## IV. Key definitions \u0026 patterns\n\nThe `poly-index` library provides several ways to define how your objects are indexed, ranging from simple field lookups to more complex composite and multi-valued keys.\n\n### 1. Simple Keys\n\nSimple keys are best for exact matching on single fields or simple transformations.\n\n```java\n// Simple field-based key\nKey\u003cUser\u003e EMAIL_KEY = Key.of(User::email);\n\n// Named key (useful for debugging and custom indexing logic)\nKey\u003cUser\u003e NAME_KEY = Key.of(\"user-name\", User::name);\n\n// Key with a custom transformation\nKey\u003cProduct\u003e BRAND_MODEL_KEY = Key.of(p -\u003e p.brand() + \":\" + p.model());\n\n// Key with specific MapIndexType (stores all matches for the same key)\nKey\u003cProduct\u003e CAT_KEY = Key.of(Product::category, MapIndexType.ALL);\n```\n\n### 2. MapCombinationKey (composite indices)\n\n`MapCombinationKey` is the primary way to define indices based on multiple fields. It can accept a `requires` clause (fields that must be non-null) and/or `excludes` clause (fields must be null).\n\nBasic composite key:\n\n```java\n// Matches ONLY if both brand and model are present\npublic static final Key\u003cVehicle\u003e BRAND_MODEL_KEY = MapCombinationKey.of(\n    requires(Vehicle::brand, Vehicle::model),\n    MapIndexType.FIRST\n);\n```\n\nUsing requirements and exclusions:\n\n```java\npublic record Product(String category, String subCategory, String sku, String tag) {\n    /* Matches ONLY if category, subCategory and sku are all present */\n    public static final Key\u003cProduct\u003e CAT_SUB_SKU_KEY = MapCombinationKey.of(\n        requires(Product::category, Product::subCategory, Product::sku),\n        MapIndexType.FIRST\n    );\n\n    /* Matches if category and subCategory are present, but ONLY if sku is NULL */\n    public static final Key\u003cProduct\u003e CAT_SUB_KEY = MapCombinationKey.of(\n        requires(Product::category, Product::subCategory),\n        excludes(Product::sku),\n        MapIndexType.FIRST\n    );\n}\n```\n\nA single key can support multiple \"variants\" of indexing requirements.\n\n```java\n// A key that matches EITHER (brand + model) OR (brand + licensePlate)\nKey\u003cVehicle\u003e MULTI_VARIANT_KEY = MapCombinationKey.of(List.of(\n    MapCombinationKey.variant(requires(Vehicle::brand, Vehicle::model)),\n    MapCombinationKey.variant(requires(Vehicle::brand, Vehicle::licensePlate))\n), MapIndexType.FIRST);\n```\n\n### 3. MapIndexType \u0026 Strategies\n\nWhen indexing multiple objects that might share the same key value, `MapIndexType` (or custom `MapIndexStrategy`) defines which ones are kept:\n\n* `ALL`: (default) stores all objects matching the key in a list.\n* `FIRST`: only stores the first object encountered for a given key value. Subsequent objects are ignored.\n* `LAST`: only stores the last object encountered. Each new object replaces the previous one for that key.\n\n### 4. Handling multi-valued Keys\n\nFor scenarios like matching against a list of tags or variants, use custom functions returning an `IndexKeyCollection`.\n\n```java\npublic static final Key\u003cProduct\u003e TAG_KEY = MapCombinationKey.of(\n    requires(Product::category),\n    new IndexFirstStrategy\u003c\u003e(entity -\u003e {\n        // Generate multiple index entries from a single field\n        List\u003cString\u003e tags = Arrays.asList(entity.tag().split(\",\"));\n        return IndexKeyCollection.of(tags);\n    })\n);\n```\n\n### 5. Lucene-based Indexing (fuzzy \u0026 prefix-based lookup)\n\nFor more advanced search requirements like fuzzy matching or prefix-based lookups, you can use Lucene-based keys. These leverage an in-memory Lucene index while maintaining the same `IndexedStore` API.\n\n```java\n// Fuzzy match: matches \"Doe\" even if searched as \"Doo\"\nKey\u003cPerson\u003e FUZZY_KEY = Key.ofLucene(\"fuzzy\", Person::lastName, new FuzzyMatchStrategy());\n\n// Prefix match: matches \"Doe\" if searched as \"Do\"\nKey\u003cPerson\u003e PREFIX_KEY = Key.ofLucene(\"prefix\", Person::lastName, new PartialMatchStrategy());\n\n// Querying remains consistent with map-based stores\nOptional\u003cPerson\u003e p = store.getFirst(\"Doo\", FUZZY_KEY);\n```\n\n### 6. Advanced Lucene Queries\n\n`Key.ofLuceneQuery` provides full control over how Lucene `Document`s are created and how `Query` objects are parsed.\n\n```java\npublic static final Key\u003cPerson\u003e ADVANCED_KEY = Key.ofLuceneQuery(\n    person -\u003e List.of(\n        new StringField(\"fname\", person.firstName(), Field.Store.YES),\n        new StringField(\"lname\", person.lastName(), Field.Store.YES)\n    ),\n    (parser, criteria) -\u003e parser.parse(\n        \"fname:\" + criteria.firstName() + \" AND lname:\" + criteria.lastName()\n    )\n);\n```\n\n## V. Dev Installation\n\nThis project will require you to have the following:\n\n* Java 17+\n* Git (versioning)\n* Maven (dependency resolving, publishing and packaging) \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filluin-tech%2Fpoly-index","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filluin-tech%2Fpoly-index","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filluin-tech%2Fpoly-index/lists"}