Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rutledgepaulv/q-builders
Type safe database agnostic query builders.
https://github.com/rutledgepaulv/q-builders
elasticsearch mongodb query-builder query-dsl rsql
Last synced: 2 months ago
JSON representation
Type safe database agnostic query builders.
- Host: GitHub
- URL: https://github.com/rutledgepaulv/q-builders
- Owner: RutledgePaulV
- License: mit
- Created: 2015-10-04T22:03:17.000Z (over 9 years ago)
- Default Branch: develop
- Last Pushed: 2022-06-25T07:28:00.000Z (over 2 years ago)
- Last Synced: 2024-10-13T05:30:57.820Z (3 months ago)
- Topics: elasticsearch, mongodb, query-builder, query-dsl, rsql
- Language: Java
- Homepage:
- Size: 233 KB
- Stars: 55
- Watchers: 5
- Forks: 26
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![Build Status](https://travis-ci.org/RutledgePaulV/q-builders.svg)](https://travis-ci.org/RutledgePaulV/q-builders)
[![Coverage Status](https://coveralls.io/repos/RutledgePaulV/q-builders/badge.svg?branch=develop&service=github)](https://coveralls.io/github/RutledgePaulV/q-builders?branch=develop)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.rutledgepaulv/q-builders/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.rutledgepaulv/q-builders)### Overview
A lightweight abstraction for constructing queries oriented around domain models / entities that minimizes
magic strings, provides type safety, produces queries that read well, and provides a decoupled way to define new query target formats - allowing you to change your mind about where you store your data without having to change all of your query code.### Why does this exist?
A lot of existing query builders are lacking. It's difficult to write a query builder that is both convenient and safe, which has resulted in most query builders giving up on type safety or allowing you to call methods that don't make sense to be able to call at that time.### Why is this better?
It uses the type system to enforce that you won't call an unapplicable method at any point as you build your queries. Also, there's no need to worry about someone passing an integer to a string field, etc. It supports both chaining and composition to build a query and when used with static imports it becomes a succinct (as far as java goes) query DSL.### Out Of Box Target Formats:
- Java Predicates
- A string in RSQL format
- Elasticsearch's QueryBuilder
- Spring Data's MongoDB Criteria### Simple Usage:
```java
//--------------------------------------------------------------------------
// define a single query model for each of the models you want to be able to
// query against. Return the appropriate property interface for each field
// based on the type of the value on your model
//--------------------------------------------------------------------------public class PersonQuery extends QBuilder {
public StringProperty firstName() {
return stringField("firstName");
}
public IntegerProperty age() {
return integerField("age");
}
}Condition q = new PersonQuery().firstName().eq("Paul").and().age().eq(23);
String rsql = q.query(new RSQLVisitor());
// firstName==Paul;age==23Criteria mongoCriteria = q.query(new MongoVisitor());
// {firstName: "Paul", age: 23}FilterBuilder filter = q.query(new ElasticsearchVisitor());
// { "and" : { "filters" : [ { "term" : { "firstName" : "Paul" } }, { "term" : { "age" : 23 } } ] } }Predicate predicate = q.query(new PredicateVisitor<>());
// List personsNamedPaulAndAge23 = persons.stream().filter(predicate).collect(toList());
```### Static Import Usage:
```javapublic class PersonQuery extends QBuilder {
public static StringProperty firstName() {
return new PersonQuery().stringField("firstName");
}
public static IntegerProperty age() {
return new PersonQuery().integerField("age");
}
}import static com.company.queries.PersonQuery.*;
Condition query = firstName().eq("Paul").or(and(firstName().ne("Richard"), age().gt(22)));
```### Precedence:
Chaining with the infix forms of ```and()``` and ```or()``` is complicated when you use both and then want to talk about
precedence. The implementation is such that whenever you change from a chain of ```and()``` to
a chain of ```or()``` (or vice versa), then the previous statements are wrapped together and the existing set
becomes one of the elements in the new ```or()``` (or ```and()```) chain.In general, to avoid unintended precedence concerns, it's best to limit your chains
to only ```and()``` or ```or()``` operators and use the compositional forms
```and(Condition c1, Condition c2, Condition... cn)``` and
```or(Condition c1, Condition c2, Condition... cn)``` for queries that must mix the two.### Common Use Cases
#### Such-&-Such Isn't Easy to Use or Type Safe
Many criteria / query builders don't provide much in the way of a good "user experience". You can use q-builders simply because they provide an improvement over these.#### I Might Change Datastores
By using a layer that provides some decoupling from your storage, if you decide to swap out a datastore for something else but you're not also changing your data's structure then you can just write a new target backend and keep your query building the same.#### I'm Providing a Rest API
Chances are you want to provide an ability for people to query against your API, but you also make queries against the database yourself in the implementation of business logic on the server. One option could be to use these builders to define one query model in a shared jar that you use in both your SDK and API and simply target different query formats. Like RSQL for over-the-wire and directly into mongo criteria on the API server.### RSQL Flavor
The RSQL builder introduces some new operators to the standard RSQL set. Since this library only
builds queries it doesn't dictate what you use to parse them. However, it's written specifically
to be compatible with [rsql-parser](https://github.com/jirutka/rsql-parser). So, you should
make sure that you add the following operators before parsing:- "=ex=" The exists clause. It has values of either ```true``` or ```false```.
- "=q=" The subquery clause. It has a string value that itself might be an entire RSQL query.
- "=re=" A regular expression as a string. The string will be passed as-is to the backend visitor you use, so the regex string must be in the same flavor as the visitor you intend to use (mongo regex vs java regex, etc)### Installation
#### Release Versions
```xml
com.github.rutledgepaulv
q-builders
1.5
```
#### Snapshot Versions
```xml
com.github.rutledgepaulv
q-builders
1.6-SNAPSHOT
ossrh
Repository for snapshots
https://oss.sonatype.org/content/repositories/snapshots
true
```
#### Optional dependencies
```xml
org.springframework.data
spring-data-mongodb
1.9.2.RELEASE
org.elasticsearch
elasticsearch
2.3.4
```
### License
This project is licensed under [MIT license](http://opensource.org/licenses/MIT).