{"id":29401036,"url":"https://github.com/turkraft/springfilter","last_synced_at":"2025-07-10T15:04:23.353Z","repository":{"id":37857028,"uuid":"336983059","full_name":"turkraft/springfilter","owner":"turkraft","description":"Dynamically filter JPA entities and Mongo collections with a user-friendly query syntax. Seamless integration with Spring APIs. Star to support the project! ⭐️","archived":false,"fork":false,"pushed_at":"2025-07-01T12:57:02.000Z","size":1161,"stargazers_count":249,"open_issues_count":21,"forks_count":38,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-07-09T14:14:09.019Z","etag":null,"topics":["filter","hibernate","java","jpa","mongodb","odata","query","search","spring"],"latest_commit_sha":null,"homepage":"https://turkraft.com/springfilter","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/turkraft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"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},"funding":{"github":["torshid"]}},"created_at":"2021-02-08T06:37:47.000Z","updated_at":"2025-07-01T17:44:43.000Z","dependencies_parsed_at":"2023-09-23T14:35:26.358Z","dependency_job_id":"f960fed7-cf6c-47bd-a071-8514921afe3c","html_url":"https://github.com/turkraft/springfilter","commit_stats":{"total_commits":560,"total_committers":7,"mean_commits":80.0,"dds":0.3857142857142857,"last_synced_commit":"ab12cf408ef18b5d84b01024f474e81262966d7b"},"previous_names":["turkraft/spring-filter"],"tags_count":80,"template":false,"template_full_name":null,"purl":"pkg:github/turkraft/springfilter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/turkraft%2Fspringfilter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/turkraft%2Fspringfilter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/turkraft%2Fspringfilter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/turkraft%2Fspringfilter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/turkraft","download_url":"https://codeload.github.com/turkraft/springfilter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/turkraft%2Fspringfilter/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264474212,"owners_count":23614018,"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":["filter","hibernate","java","jpa","mongodb","odata","query","search","spring"],"created_at":"2025-07-10T15:03:01.551Z","updated_at":"2025-07-10T15:04:22.070Z","avatar_url":"https://github.com/turkraft.png","language":"Java","readme":"# Spring Filter\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/turkraft/springfilter\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/turkraft/springfilter/main/.github/logo.png?raw=true\" alt=\"Spring Filter Logo\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nAre you looking for an effortless way to dynamically filter entities? Look no further than Spring Filter. With Spring Filter, your API will benefit from a comprehensive search functionality. Even if you don't have a web API, you can still leverage the powerful filter builder to generate complex SQL or Mongo queries.\n\nThe library's modular design and seamless integration with Spring make it easy to extend with custom operators and functions, or even integrate it into a different platform. Say goodbye to the headache of generating valid queries in frontend applications, as JavaScript filter builders are also available to simplify the process.\n\n\u003cdetails\u003e\n  \u003csummary\u003e:warning: \u003cb\u003e\u003cu\u003eAbout Release 3.0.0\u003c/u\u003e\u003c/b\u003e\u003c/summary\u003e\n  \n  \u003e [Spring Filter 3.0.0](https://github.com/turkraft/springfilter/issues/254) is a new release built from the ground up. It includes much better integration with Spring, with many new features, enhancements and bug fixes.\n  \u003e The language syntax didn't change, frontend applications will therefore not require any modification.\n  \u003e The new `FilterBuilder` class is incompatible with the previous one and other breaking changes are present but the basic usage of the library remains similar.\n  \u003e Please feel free to [create an issue](https://github.com/turkraft/spring-filter/issues) if you notice anything wrong. [Consider supporting the project by sponsoring us](https://github.com/sponsors/torshid).\n  \n  \u003e You can access the older version in the [2.x.x branch](https://github.com/turkraft/spring-filter/tree/2.x.x).\n\u003c/details\u003e\n\n## Example ([try it live](https://springfilter-jpa.onrender.com/))\n\n*/search?filter=* **average**(ratings) **\u003e** 4.5 **and** brand.name **in** ['audi', 'land rover'] **and** (year **\u003e** 2018 **or** km **\u003c** 50000) and color **:** 'white' **and** accidents **is empty**\n\n```java\n/* Entity used in the query above */\n@Entity public class Car {\n  @Id long id;\n      int year;\n      int km;\n  @Enumerated Color color;\n  @ManyToOne Brand brand;\n  @OneToMany List\u003cAccident\u003e accidents;\n  @ElementCollection List\u003cInteger\u003e ratings;\n  // ...\n}\n```\n\n\u003e :rocket: Yes we support booleans, dates, enums, functions, **and even relations**! Need something else? [Tell us here](https://github.com/turkraft/spring-filter/issues).\n\n## [Sponsors](https://github.com/sponsors/torshid)\n\nSponsor our project and gain the advantage of having your issues prioritized for prompt resolution.\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ca href=\"https://github.com/ixorbv\"\u003e\u003cimg width=\"64\" src=\"https://avatars.githubusercontent.com/u/127401397?v=4\"/\u003e\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n## Integrations and Usages\n\n### JPA Integration\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.turkraft.springfilter\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa\u003c/artifactId\u003e\n  \u003cversion\u003e3.1.9\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n```java\n@GetMapping(value = \"/search\")\nPage\u003cEntity\u003e search(@Filter Specification\u003cEntity\u003e spec, Pageable page) {\n    return repository.findAll(spec, page);\n}\n```\n\nThe repository should implement `JpaSpecificationExecutor` in order to execute Spring's Specification, `SimpleJpaRepository` is a well known implementation. You can remove the `Pageable` argument and return a `List` if pagination and sorting are not needed.\n\n### Mongo Integration\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.turkraft.springfilter\u003c/groupId\u003e\n  \u003cartifactId\u003emongo\u003c/artifactId\u003e\n  \u003cversion\u003e3.1.9\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n```java\n@GetMapping(value = \"/search\")\nPage\u003cEntity\u003e search(@Filter(entityClass = Entity.class) Query query, Pageable page) {\n    return mongoTemplate.find(query.with(pageable), Entity.class);\n}\n```\n\n#### Using MongoRepository\n\n```java\npublic interface EntityRepository extends MongoRepository\u003cEntity, String\u003e {\n  @Query(\"?0\")\n  List\u003cEmployee\u003e findAll(Document document);\n  @Query(\"?0\")\n  Page\u003cEmployee\u003e findAll(Document document, Pageable pageable);\n}\n\n@GetMapping(value = \"/search\")\nPage\u003cEntity\u003e search(@Filter(entityClass = Entity.class) Document document, Pageable page) {\n    return entityRepository.findAll(query, page);\n}\n```\n\n### Filter Builder\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.turkraft.springfilter\u003c/groupId\u003e\n  \u003cartifactId\u003ecore\u003c/artifactId\u003e\n  \u003cversion\u003e3.1.9\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n```java\n@Autowired FilterBuilder fb;\nFilterNode filter = fb.field(\"year\").equal(fb.input(2023)).and(fb.isNull(fb.field(\"category\"))).get();\n\n@Autowired ConversionService cs;\nString query = cs.convert(filter, String.class); // year : 2023 and category is null\n```\n\nPlease note that Spring's `ConversionService` is internally used when converting objects to strings and vice-versa.\nSpring Filter does not enforce any pattern for dates and other types.\nCustomization should be done directly within Spring if required.\n\n### JavaScript Query Builder\n\nInstead of manually writing string queries in your frontend applications, you may use\nthe [JavaScript query builder](https://github.com/sisimomo/Spring-Filter-Query-Builder).\n\n```javascript\nimport { sfAnd, sfEqual, sfGt, sfIsNull, sfLike, sfNot, sfOr } from 'spring-filter-query-builder';\n\nconst filter = sfAnd([\n  sfAnd([sfEqual('status', 'active'), sfGt('createdAt', '1-1-2000')]),\n  sfOr([sfLike('value', '*hello*'), sfLike('name', '*world*')]),\n  sfNot(sfOr([sfGt('id', 100), sfIsNull('category.order')])),\n]);\n\nconst req = await fetch('http://api/person?filter=' + filter.toString());\n```\n\n### Angular Query Builder\n\nPlease see [documentation](https://github.com/68ociredef/spring-filter-ng).\n\n## Syntax\n\n### Fields\n\n`field`, `field.nestedField`\n\n### Inputs\n\n`123`, `-321.123`, `true`, `false`, `'hello world'`, `'escape \\' quote'`, `'1-01-2023'`\n\n### Collections\n\n`[1, 2, 3]`, `[field, ['x', 'y'], 99]`\n\n### Functions\n\n`f()`, `f(x)`, `f(x, y)`\n\n### Placeholders\n\n`` `place_holder` ``\n\n### Priority\n\n`x and (y or z)`\n\n### Prefix Operators\n\n`op expr`, `not ready`\n\n### Infix Operators\n\n`expr op expr`, `x and y`\n\n### Postfix Operators\n\n`expr op`, `field is null`\n\n## Common Language\n\nBelow are listed the operators and functions which are supported by all integrations (JPA and Mongo).\nIntegrations may extend this common language.\n\n### Logical Operators\n\n\u003ctable\u003e\n  \u003ctr\u003e \u003cth\u003eLiteral\u003c/th\u003e \u003cth\u003eDescription\u003c/th\u003e \u003cth\u003eExample\u003c/th\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003eand\u003c/th\u003e \u003ctd\u003eand's two expressions\u003c/td\u003e \u003ctd\u003estatus : 'active' \u003cb\u003eand\u003c/b\u003e createdAt \u003e '1-1-2000'\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003eor\u003c/th\u003e \u003ctd\u003eor's two expressions\u003c/td\u003e \u003ctd\u003evalue ~ '*hello*' \u003cb\u003eor\u003c/b\u003e name ~ '*world*'\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003enot\u003c/th\u003e \u003ctd\u003enot's an expression\u003c/td\u003e \u003ctd\u003e \u003cb\u003enot\u003c/b\u003e (id \u003e 100 or category.order is null) \u003c/td\u003e \u003c/tr\u003e\n\u003c/table\u003e\n\n### Value Comparators\n\n\u003ctable\u003e\n  \u003ctr\u003e \u003cth\u003eLiteral\u003c/th\u003e \u003cth\u003eDescription\u003c/th\u003e \u003cth\u003eExample\u003c/th\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e~\u003c/th\u003e \u003ctd\u003echecks if the left (string) expression is similar to the right (string) expression\u003c/td\u003e \u003ctd\u003ecatalog.name \u003cb\u003e~\u003c/b\u003e '*electronic*'\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e~~\u003c/th\u003e \u003ctd\u003esimilar to the previous operator but case insensitive\u003c/td\u003e \u003ctd\u003ecatalog.name \u003cb\u003e~~\u003c/b\u003e 'ElEcTroNic*'\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e:\u003c/th\u003e \u003ctd\u003echecks if the left expression is equal to the right expression\u003c/td\u003e \u003ctd\u003eid \u003cb\u003e:\u003c/b\u003e 5\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e!\u003c/th\u003e \u003ctd\u003echecks if the left expression is not equal to the right expression\u003c/td\u003e \u003ctd\u003eusername \u003cb\u003e!\u003c/b\u003e 'torshid'\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e\u003e\u003c/th\u003e \u003ctd\u003echecks if the left expression is greater than the right expression\u003c/td\u003e \u003ctd\u003edistance \u003cb\u003e\u003e\u003c/b\u003e 100\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e\u003e:\u003c/th\u003e \u003ctd\u003echecks if the left expression is greater or equal to the right expression\u003c/td\u003e \u003ctd\u003edistance \u003cb\u003e\u003e:\u003c/b\u003e 100\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e\u003c\u003c/th\u003e \u003ctd\u003echecks if the left expression is smaller than the right expression\u003c/td\u003e \u003ctd\u003edistance \u003cb\u003e\u003c\u003c/b\u003e 100\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e\u003c:\u003c/th\u003e \u003ctd\u003echecks if the left expression is smaller or equal to the right expression\u003c/td\u003e \u003ctd\u003edistance \u003cb\u003e\u003c:\u003c/b\u003e 100\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003eis null\u003c/th\u003e \u003ctd\u003echecks if an expression is null\u003c/td\u003e \u003ctd\u003estatus \u003cb\u003eis null\u003c/b\u003e\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003eis not null\u003c/th\u003e \u003ctd\u003echecks if an expression is not null\u003c/td\u003e \u003ctd\u003estatus \u003cb\u003eis not null\u003c/b\u003e\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003eis empty\u003c/th\u003e \u003ctd\u003echecks if the (collection) expression is empty\u003c/td\u003e \u003ctd\u003echildren \u003cb\u003eis empty\u003c/b\u003e\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003eis not empty\u003c/th\u003e \u003ctd\u003echecks if the (collection) expression is not empty\u003c/td\u003e \u003ctd\u003echildren \u003cb\u003eis not empty\u003c/b\u003e\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003ein\u003c/th\u003e \u003ctd\u003echecks if an expression is present in the right expressions\u003c/td\u003e \u003ctd\u003estatus \u003cb\u003ein [\u003c/b\u003e'initialized'\u003cb\u003e,\u003c/b\u003e 'active'\u003cb\u003e]\u003c/b\u003e\u003c/td\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003enot in\u003c/th\u003e \u003ctd\u003echecks if an expression is not present in the right expressions\u003c/td\u003e \u003ctd\u003estatus \u003cb\u003enot in [\u003c/b\u003e'failed'\u003cb\u003e,\u003c/b\u003e 'closed'\u003cb\u003e]\u003c/b\u003e\u003c/td\u003e \u003c/tr\u003e\n\u003c/table\u003e\n\n### Functions\n\n\u003ctable\u003e\n  \u003ctr\u003e \u003cth\u003eName\u003c/th\u003e \u003cth\u003eDescription\u003c/th\u003e \u003cth\u003eExample\u003c/th\u003e \u003c/tr\u003e\n  \u003ctr\u003e \u003ctd\u003e size \u003c/th\u003e \u003ctd\u003e returns the collection's size \u003c/td\u003e \u003ctd\u003e \u003cb\u003esize(\u003c/b\u003eaccidents\u003cb\u003e)\u003c/b\u003e \u003c/td\u003e \u003c/tr\u003e\n\u003c/table\u003e\n\n## Articles\n\n* [Easily filter entities in your Spring API](https://torshid.medium.com/easily-filter-entities-in-your-spring-api-f433537cfd41)\n\n## Contributing\n\nIdeas and pull requests are always welcome.\n[Google's Java Style](https://github.com/google/styleguide/blob/gh-pages/eclipse-java-google-style.xml)\nis used for formatting.\n\n## Contributors\n\n* Thanks to [@marcopag90](https://github.com/marcopag90) and [@glodepa](https://github.com/glodepa)\n  for adding support to MongoDB.\n* Thanks to [@sisimomo](https://github.com/sisimomo) for creating\n  the [JavaScript query builder](https://github.com/sisimomo/Spring-Filter-Query-Builder).\n* Thanks to [@68ociredef](https://github.com/68ociredef) for creating\n  the [Angular query builder](https://github.com/68ociredef/spring-filter-ng).\n\n## License\n\nDistributed under the [MIT license](LICENSE).\n","funding_links":["https://github.com/sponsors/torshid"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fturkraft%2Fspringfilter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fturkraft%2Fspringfilter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fturkraft%2Fspringfilter/lists"}