-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
0021 Generic Finds DRAFT -> REVIEW #54
Closed
Closed
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
99b7f5c
Initial draft of simplified querying
simonbasle 39ea301
rename findAll to findAllLike
simonbasle 74d6557
rework the idea of operators map/builder, list all NOT operators, rem…
simonbasle 76cad85
rework 2 alternative APIs with operators, added BETWEEN back
simonbasle 58d2147
added the limitation/question of OR
simonbasle d73de47
add CONTAINS to changelog
simonbasle File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
# Meta | ||
|
||
- RFC Name: Generic Find Querying | ||
- RFC ID: 0021 | ||
- Start Date: 2016-09-07 | ||
- Owner: @simonbasle | ||
- Current Status: DRAFT | ||
|
||
# Summary | ||
Performing simple selects without writing any N1QL. | ||
|
||
# Motivation | ||
For simple querying cases, shortcircuiting N1QL altogether and having a simple | ||
API can be valuable. | ||
|
||
# General Design | ||
|
||
## Query-by-Example | ||
The goal of querying by example is to provide an example of what the user is | ||
looking for in terms of criterias, and the SDK will return all matching | ||
documents that match these criterias. | ||
|
||
As there is no concept of an entity there, the criterias can simply be | ||
expressed as a form of JSON object (so native JSON in Node, `JsonObject` in | ||
Java, etc...). | ||
|
||
Let's imagine that one wants to find every document that has a `lastname` field | ||
equals to `Doe`, as well as an `age` field equals to `21`. This could be | ||
achieved using query-by-example, eg. in Java: | ||
|
||
```java | ||
JsonObject example = JsonObject.create() | ||
.put("lastname", "Doe") | ||
.put("age", 21); | ||
|
||
N1qlQueryResult result = bucket.findAllLike(example); | ||
``` | ||
|
||
Which would translate, in the `Bucket` "foo", to the following N1QL: | ||
|
||
```sql | ||
SELECT * FROM `foo` WHERE lastname = 'Doe' AND age = 21; | ||
``` | ||
|
||
## Matching on criterias other than `equals` | ||
By default, all fields in the provided JSON example are matched against by | ||
using the `=` N1QL operator. What if one wants a different criteria? For | ||
instance, in our former example, what if I wanted all documents where the name | ||
is "Doe" but the age is lesser than 21? | ||
|
||
An alternative API for constructing the example could be proposed, that would | ||
allow to both specify a value and an operator for each criteria. | ||
|
||
The default simplified version of `findAllLike` would not provide the | ||
operators, defaulting in effect each field to an `EQUALS` operator. | ||
|
||
When done expressing the criterias, `findAllLike` would call on a `toN1ql()` | ||
method to produce the full N1QL, for example: | ||
|
||
```sql | ||
SELECT * FROM `foo` WHERE lastname = "Doe" AND age <= 21; | ||
``` | ||
|
||
The following operators would need to be supported: | ||
* `EQUALS`: implicit one used if a field from the example isn't found in the operators map. | ||
* `LIKE` | ||
* `CONTAINS`: translates to an `IN` keyword, inverted logic to be able to write something like "array CONTAINS aValue". | ||
* `IS_NULL` | ||
* `IS_MISSING` | ||
* `IS_VALUED` | ||
* `GREATER_THAN` | ||
* `GREATER_THAN_EQUALS` | ||
* `LESSER_THAN` | ||
* `LESSER_THAN_EQUALS` | ||
* `BETWEEN` (needs 2 values) | ||
* The negation of most of the above: `NOT_EQUALS`, `NOT_LIKE`, `NOT_CONTAINS`, | ||
`IS_NOT_NULL`, `IS_NOT_MISSING`, `IS_NOT_VALUED`, `NOT_BETWEEN` | ||
|
||
### API alternative 1 (builder-friendly SDKs) | ||
A *builder* like interface could be provided as a fluent API to specify both | ||
fields, values and operators in one go: | ||
|
||
```java | ||
Example example = Example.of("lastname").not().equalTo("Doe") | ||
.and("age").greaterThan(20); | ||
|
||
N1qlQueryResult result = bucket.findAllLike(example); | ||
``` | ||
|
||
Would translate to this N1QL: | ||
|
||
```sql | ||
SELECT * FROM `foo` WHERE lastname != 'Doe' AND age > 20; | ||
``` | ||
|
||
The builder methods in Java for each "positive" operator above would be: | ||
|
||
```java | ||
Criteria.of("a").equalTo("foo") | ||
.and("b").greaterThan(1) | ||
.and("c").greaterThanOrEqualTo(2) | ||
.and("d").lesserThan(4) | ||
.and("e").lesserThanOrEqualTo(3) | ||
.and("f").like("%toto%") | ||
.and("g").isNull() | ||
.and("h").isValued() | ||
.and("i").isMissing() | ||
.and("j").contains("bar") | ||
.and("k").between(100, 200); | ||
``` | ||
|
||
### API alternative 2 | ||
For languages for which a builder API isn't practical, an alternative JSON | ||
convention can be integrated. | ||
|
||
Each operator mentioned above would be affected a string representation with a | ||
`$` prefix, like `$gte` for `GREATER_THAN_EQUALS`. This string could then be | ||
combined with the value in the JSON object passed to `findAllLike()`, as a sub | ||
object with the operator as key and the value as value. For example in Node: | ||
|
||
`findAllLike({ "lastName": { "$neq": "Doe" }, "age": { "$gt": 20 } })` | ||
|
||
Which would also translate to this N1QL: | ||
|
||
```sql | ||
SELECT * FROM `foo` WHERE lastname != 'Doe' AND age > 20; | ||
``` | ||
|
||
## Limitations | ||
Anything other than a basic comparison operation as listed above is out of | ||
scope for this RFC, and users must then craft their own N1QL statements (either | ||
by hand or using any available DSL). | ||
|
||
This goes for example for functions, array construction operators, CASE | ||
constructs, ... | ||
|
||
Criterias are for now only linked by a logical AND. | ||
|
||
## Errors | ||
N/A so far. The results are presented in the same form and with same error | ||
handling conditions as with `Bucket#query`. | ||
|
||
## Documentation | ||
Probably needs its own section in the querying using the SDK pages. | ||
|
||
# Language Specifics | ||
TBD | ||
|
||
# Questions | ||
- Should `or` be supported? (note this can increase the complexity for the builder API) | ||
|
||
# Changelog | ||
- 2016-09-07: Initial draft publication | ||
- 2016-09-08: reworked the matchers/operators idea and builder, removed BETWEEN (added to open questions), added explicit list of "NOT" Operators. | ||
- 2016-09-15: Re-added between, expressed two alternatives to specify operators (JSON convention and builder API). CONTAINS should be used for the “is value x in the array field y?” case rather than a convenience method over LIKE. | ||
|
||
# Signoff | ||
If signed off, each representative agrees both the API and the behavior will be implemented as specified. | ||
|
||
| Language | Representative | Date | | ||
| -------- | -------------- | ---------- | | ||
| | | | |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably phrase this differently. It's not so much that avoiding N1QL is a goal but rather to keep the simple things simple. There are lots of situations where just the predicate is needed.