{"id":29116820,"url":"https://github.com/SchwarzIT/hypermatch","last_synced_at":"2025-06-29T11:14:05.793Z","repository":{"id":254812213,"uuid":"847584852","full_name":"SchwarzIT/hypermatch","owner":"SchwarzIT","description":"hypermatch is a high-performance ⚡ Go library designed for rapid matching of a large number of rules to events. It processes thousands of events per second 🚀 against extensive rule sets in-memory with minimal latency ⏱️.","archived":false,"fork":false,"pushed_at":"2025-02-10T01:58:25.000Z","size":319,"stargazers_count":26,"open_issues_count":1,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-06T14:39:21.955Z","etag":null,"topics":["event-driven","events","go","golang","json","matching","matching-engine","performance","rule-engine"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SchwarzIT.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":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-26T06:35:35.000Z","updated_at":"2025-03-31T15:45:28.000Z","dependencies_parsed_at":"2024-12-02T15:20:15.221Z","dependency_job_id":"c6b55155-416c-4bbc-8cd1-a22198c85c4b","html_url":"https://github.com/SchwarzIT/hypermatch","commit_stats":null,"previous_names":["schwarzit/hypermatch"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/SchwarzIT/hypermatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SchwarzIT%2Fhypermatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SchwarzIT%2Fhypermatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SchwarzIT%2Fhypermatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SchwarzIT%2Fhypermatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SchwarzIT","download_url":"https://codeload.github.com/SchwarzIT/hypermatch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SchwarzIT%2Fhypermatch/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262581513,"owners_count":23331925,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["event-driven","events","go","golang","json","matching","matching-engine","performance","rule-engine"],"created_at":"2025-06-29T11:13:48.669Z","updated_at":"2025-06-29T11:14:05.733Z","avatar_url":"https://github.com/SchwarzIT.png","language":"Go","readme":"[![SIT](https://img.shields.io/badge/SIT-awesome-blueviolet.svg)](https://jobs.schwarz)\n[![CI](https://github.com/SchwarzIT/hypermatch/actions/workflows/go-test.yml/badge.svg)](https://github.com/SchwarzIT/hypermatch/actions/workflows/go-test.yml)\n[![Coverage Status](https://coveralls.io/repos/github/SchwarzIT/hypermatch/badge.svg?branch=main)](https://coveralls.io/github/SchwarzIT/hypermatch?branch=main)\n[![Go Report Card](https://goreportcard.com/badge/github.com/SchwarzIT/hypermatch)](https://goreportcard.com/report/github.com/SchwarzIT/hypermatch)\n[![Go Reference](https://pkg.go.dev/badge/github.com/schwarzit/hypermatch.svg)](https://pkg.go.dev/github.com/schwarzit/hypermatch)\n![License](https://img.shields.io/github/license/SchwarzIT/hypermatch)\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/SchwarzIT/hypermatch)\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)  \n\n![hypermatch logo](./logo/logo-small.png)\n\n# Introduction\nHypermatch is a high-performance Go library that enables rapid matching of a large number of rules against events. Designed for speed and efficiency, hypermatch handles thousands of events per second with low latency, making it ideal for real-time systems.\n\n- **Fast Matching**: Matches events to a large set of rules in-memory with minimal delay  ... [it's really fast! (Benchmark)](_benchmark/benchmark.md)\n- **Readable Rule Format**: Serialize rules into human-readable JSON objects.\n- **Flexible Rule Syntax**: Supports various matching conditions, including equals, prefix, suffix, wildcard, anything-but, all-of, and any-of.\n\nAn event consists of a list of fields, provided as name/value pairs. A rule links these event fields to patterns that determine whether the event matches.\n\n![example](./example.png)\n\n# Quick Start\n\n```go\nimport (\n    hypermatch \"github.com/SchwarzIT/hypermatch\"\n)\n\nfunc main() {\n    //Initialize hypermatch\n    hm := hypermatch.NewHyperMatch()\n    \n    //Add a rule\n    if err := hm.AddRule(\"markus_rule\", hypermatch.ConditionSet{\n        hypermatch.Condition{Path: \"firstname\", Pattern: hypermatch.Pattern{Type: hypermatch.PatternEquals, Value: \"markus\"}},\n        hypermatch.Condition{Path: \"lastname\", Pattern: hypermatch.Pattern{Type: hypermatch.PatternEquals, Value: \"troßbach\"}},\n        }); err != nil {\n            panic(err)\n    }\n    \n    //Test with match\n    matchedRules := hm.Match([]hypermatch.Property{\n        {Path: \"firstname\", Values: []string{\"markus\"}},\n        {Path: \"lastname\", Values: []string{\"troßbach\"}},\n    })\n    log.Printf(\"Following rules matches: %v\", matchedRules)\n    \n    //Test without match\n    matchedRules = hm.Match([]hypermatch.Property{\n        {Path: \"firstname\", Values: []string{\"john\"}},\n        {Path: \"lastname\", Values: []string{\"doe\"}},\n    })\n    log.Printf(\"Following rules matches: %v\", matchedRules)\n}\n```\n\n# Documentation\n## Example Event\n\nAn event is represented as a JSON object with various fields. Here’s a sample event:\n\n```javascript\n{\n        \"name\": \"Too many parallel requests on system xy\",\n        \"severity\": \"critical\",\n        \"status\": \"firing\",\n        \"message\": \"Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\",\n        \"team\": \"awesome-team\",\n        \"application\": \"webshop\",\n        \"component\": \"backend-service\",\n        \"tags\": [\n            \"shop\",\n            \"backend\"\n        ]   \n}\n```\n\n**This example will be referenced throughout the documentation.**\n\n## Matching Basics\n\nRules in Hypermatch are composed of conditions defined by the `ConditionSet` type.\n\n- **Case-Insensitive Matching**: All value comparisons are case-insensitive.\n- **Supported Types**: Currently, only strings and string arrays are supported.\n\nEach condition includes:\n\n- **Path**: The field in the event to match against.\n- **Pattern**: The pattern used to match the value at the specified path.\n\nHere’s an example rule that matches the event above:\n\n```go\nConditionSet{\n    {\n        Path: \"status\",\n        Pattern: Pattern{Type: PatternEquals, Value: \"firing\"},\n    },\n    {\n        Path: \"name\",\n        Pattern: Pattern{Type: PatternAnythingBut, Sub: []Pattern{\n                {Type: PatternWildcard, Value: \"TEST*\"},\n            },\n        },\n    },\n    {\n        Path: \"severity\",\n        Pattern: Pattern{ Type: PatternAnyOf,\n            Sub: []Pattern{\n                {Type: PatternEquals, Value: \"critical\"},\n                {Type: PatternEquals, Value: \"warning\"},\n            },\n        },\n    },\n    {\n        Path: \"tags\",\n        Pattern: Pattern{ Type: PatternAllOf,\n            Sub: []Pattern{\n                {Type: PatternEquals, Value: \"shop\"},\n                {Type: PatternEquals, Value: \"backend\"},\n            },\n        },\n    },\n}\n```\n\nThe rules and conditions are also expressible as JSON objects. The following JSON is the equivalent of the above Go notation for a `ConditionSet`:\n\n```javascript\n{\n    \"status\": {\n        \"equals\": \"firing\"\n    },\n    \"name\": {\n        \"anythingBut\": [\n            {\"wildcard\": \"TEST*\"}\n        ]\n    },\n    \"severity\": {\n        \"anyOf\": [\n            {\"equals\": \"critical\"},\n            {\"equals\": \"warning\"}\n        ]\n    },\n    \"tags\": {\n        \"allOf\": [\n            {\"equals\": \"shop\"},\n            {\"equals\": \"backend\"}\n        ]\n    }\n}\n```\n\n**Note**: For simplicity, all examples in this documentation will be presented in JSON format.\n\n## Matching syntax\n### \"equals\" matching\nThe `equals` condition checks if an attribute of the event matches a specified value, case-insensitively.\n\n```javascript\n{\n    \"status\": {\n        \"equals\": \"firing\"\n    }\n}\n```\n\nIf the attribute value is type of:\n\n- **String**: Checks if the value is equal to \"firing\"\n- **String array**: Checks if the array contains an element equal to \"firing\"\n\n### \"prefix\" matching\nThe `prefix` condition checks if an attribute starts with a specified prefix, case-insensitively.\n\n```javascript\n{\n    \"status\": {\n        \"prefix\": \"fir\"\n    }\n}\n```\n\nIf the attribute value is type of:\n\n- **String**: Checks if the value begins with \"fir\"\n- **String array**: Checks if the array contains an element that begins with \"fir\"\n\n### \"suffix\" matching\nThe `suffix` condition checks if an attribute ends with a specified suffix, case-insensitively.\n\n```javascript\n{\n    \"status\": {\n        \"suffix\": \"ing\"\n    }\n}\n```\n\nIf the attribute value is type of:\n\n- **String**: Checks if the value ends with \"ing\"\n- **String array**: Checks if the array contains an element that ends with \"ing\"\n\n### \"wildcard\" matching\nThe `wildcard` condition uses wildcards to match the value of an attribute, ignoring case.\n\n- Use * as a wildcard to match any number of characters (including none).\n- You cannot place wildcards directly next to each other.\n\n```javascript\n{\n    \"name\": {\n        \"wildcard\": \"*parallel requests*\"\n    }\n}\n```\n\nIf the attribute value is type of:\n\n- **String**: Checks if the value matches the pattern \\*parallel requests\\*\n- **String array**: Checks if any value in the array matches the pattern\n\n### \"anythingBut\" matching\nThe `anythingBut` condition negates the match, triggering only if the specified condition is not met.\n\n```javascript\n{\n    \"status\": {\n        \"anythingBut\": [\n            {\"equals\": \"firing\"}\n        ]\n    }\n}\n```\n\nIf the attribute value is type of:\n\n- **String**: Checks if the value is anything other than \"firing\"\n- **String array**: Checks if the array does *not* contain an element equal to \"firing\"\n\n### \"anyOf\" matching\n`anyOf` does correspond to a boolean \"inclusive-or\". It checks multiple conditions and matches if **any** of the conditions are true.\n\n```javascript\n{\n    \"status\": {\n        \"anyOf\": [\n            {\"equals\": \"firing\"},\n            {\"equals\": \"resolved\"}\n        ]\n    }\n}\n```\n\nIf the attribute value is type of:\n\n- **String**: Checks if the value is either \"firing\" or \"resolved\"\n- **String array**: Checks if the array contains an element equal to \"firing\" or \"resolved\" or both.\n\n### \"allOf\" matching\n`allOf` does correspond to a boolean \"and\". It checks multiple conditions and matches if **all** the conditions are true.\n\n```javascript\n{\n    \"tags\": {\n        \"allOf\": [\n            {\"equals\": \"shop\"},\n            {\"equals\": \"backend\"}\n        ]\n    }\n}\n```\n\nIf the attribute value is type of:\n\n- **String**: This condition makes no sense, as it checks if the value is equal to \"shop\" and \"backend\"\n- **String array**: Checks if the array contains both \"shop\" and \"backend\"\n\n\n# Performance\n\n**hypermatch** is designed to be blazing fast with very large numbers of rules.\nNevertheless, there are a few things to consider to get maximum performance:\n- Shorten the number of fields inside the rules, the fewer conditions, the shorter is the path to find them out.\n- Try to make the **paths** as diverse as possible in events and rules. The more heterogeneous fields, the higher the performance.\n- Reduce the number of **anyOf** conditions wherever possible\n","funding_links":[],"categories":["Messaging","消息"],"sub_categories":["Search and Analytic Databases","检索及分析资料库"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSchwarzIT%2Fhypermatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSchwarzIT%2Fhypermatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSchwarzIT%2Fhypermatch/lists"}