Skip to content

Commit

Permalink
updat docs
Browse files Browse the repository at this point in the history
  • Loading branch information
tamizhvendan committed May 15, 2020
1 parent 939463e commit 277e270
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 49 deletions.
82 changes: 59 additions & 23 deletions doc/query-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ HoneyEQL uses [EDN Query Language](https://edn-query-language.org)(EQL) to query
HoneyEQL supports two modes of using EQL.

1. `:eql.mode/strict` - The query should adhere to the specifications of EQL.
2. `:eql.mode/lenient` - It supports both EQL specifications and HoneyEQL overrides of EQL specifications.
2. `:eql.mode/lenient` - It supports both EQL specifications and HoneyEQL overrides of EQL specifications for ease of use.

Based on your requirements, you can choose between either of these during the initialization of HoneyEQL. By default HoneyEQL supports `:eql.mode/lenient`.

Expand All @@ -23,6 +23,24 @@ To select the list of attributes that we want to see in the output, we'll be usi
:customer/last-name]
```

### HoneyEQL Override

The EQL specification is agonistic of the data storage and hence it doesn't provide anything specific to database querying. As per the EQL standard, if we want to select (query) all the columns of a table, we need to specify it explicitly.

```clojure
[:actor/actor-id
:actor/first-name
:actor/last-name
:actor/last-update]
```
If a table has a lot of columns, specifying all of them in the select vector may be hard. Hence HoneyEQL provides a override to select all the columns of a table using the special attribute `*`.

```clojure
[:actor/*]
```

During query resolution, HoneyEQL replaces this attribute with all the attributes of the corresponding table.

### Selecting Join Attributes

If the attribute that we want to select is a join (relationship) attribute, then we will be using a Clojure map with a single key-value pair. The key will be the join attribute and the value will be the vector of attributes that we want to select from the related entity.
Expand All @@ -31,7 +49,7 @@ If the attribute that we want to select is a join (relationship) attribute, then
[:customer/customer-id
:customer/first-name
:customer/last-name

; one to many
{:customer/rentals
[:rental/rental-id
:rental/rental-date]}]
Expand All @@ -43,11 +61,15 @@ We can have more than one join attributes as well.
[:customer/customer-id
:customer/first-name
:customer/last-name

; one to one
{:customer/address
[:address/postal-code
:address/phone]}
; one to many
{:customer/rentals
[:rental/rental-id
:rental/rental-date]}

; many to many
{:customer/payments
[:payment/payment-id
:payment/payment-date
Expand Down Expand Up @@ -155,36 +177,50 @@ and the following examples uses parameters on the join attributes.
[:film/title]}]}
```

### HoneyEQL Override

### one-to-one relationship

![](https://www.graphqlize.org/img/address_city_country_er_diagram.png)
The EQL specification uses Clojure list for defining parameters. Because of this while using we need to use [Quote](https://clojure.org/guides/weird_characters#_quote) to prevent it from being treated as function.

```clojure
(heql/query-single
(heql/query
db-adapter
{[:city/city-id 3] [:city/city
{:city/country [:country/country]}]})
'{[:actor/actor-id 148] ; ignoring the quote here will return an error
[:actor/first-name
{(:actor/films {:order-by [[:film/title :desc]]})
[:film/title]}]})
```

### one-to-many relationship

![](https://www.graphqlize.org/img/address_city_country_er_diagram.png)
If the query involves any dynamic parameter, then we need to use [Syntax Quote](https://clojure.org/guides/weird_characters#syntax_quote) along with [Unquote](https://clojure.org/guides/weird_characters#unquote).

```clojure
(heql/query-single
db-adapter
{[:country/country-id 2] [:country/country
{:country/cities [:city/city]}]})
(let [actor-id 148]
(heql/query
db-adapter
`{[:actor/actor-id ~actor-id] ; syntax quote + unquote
[:actor/first-name
{(:actor/films {:order-by [[:film/title :desc]]})
[:film/title]}]}))
```

### many-to-many relationship
In a real-world application, these scenarios are more prevalent and hence HoneyEQL overrides this parameter specification by using a **vector instead of a list**.

![](https://www.graphqlize.org/img/film_actor_er_diagram.png)
The above query using a vector in the `:eql.mode/lenient` mode would look like

```clojure
(heql/query-single
db-adapter
{[:actor/actor-id 148] [:actor/first-name
{:actor/films [:film/title]}]})
(let [actor-id 148]
(heql/query
db-adapter
{[:actor/actor-id actor-id]
[:actor/first-name
{[:actor/films {:order-by [[:film/title :desc]]}]
[:film/title]}]}))
```

It works on parameters on the idents as well.

```clojure
{[[:customer/customer-id 148] {:order-by [:customer/first-name]}]
[:customer/customer-id
:customer/first-name
:customer/last-name]}
```
91 changes: 65 additions & 26 deletions doc/sorting.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,100 @@ HoneyEQL supports sorting using the `:order-by` parameter. It takes a vector sim

```clojure
; sorting by :language/name

; :eql.mode/lenient syntax
(heql/query
db-adapter
{[[] {:order-by [:language/name]}]
[:language/name]})

; :eql.mode/strict syntax
(heql/query
db-adapter
'{([] {:order-by [:language/name]})
[:language/name]})
; returns
({:language/name "English"} {:language/name "French"} {:language/name "German"}
{:language/name "Italian"} {:language/name "Japanese"} {:language/name "Mandarin"})
'[{([] {:order-by [:language/name]})
[:language/name]}])
```

```clojure
; sorting by :language/name in descending order

; :eql.mode/lenient syntax
(heql/query
db-adapter
'{([] {:order-by [[:language/name :desc]]}) ; vector of vector!
[:language/name]})
; returns
({:language/name "Mandarin"} {:language/name "Japanese"} {:language/name "Italian"}
{:language/name "German"} {:language/name "French"} {:language/name "English"})
{[[] {:order-by [[:language/name :desc]]}]
[:language/name]})

; :eql.mode/strict syntax
(heql/query
db-adapter
'[{([] {:order-by [[:language/name :desc]]})
[:language/name]}])
```

```clojure
; sorting by multiple attributes
; :actor/first-name is ascending order and then :actor/last-name in descending order

; :eql.mode/lenient syntax
(heql/query
db-adapter
'{([] {:order-by [:actor/first-name [:actor/last-name :desc]]
:limit 2})
[:actor/first-name :actor/last-name]})
; returns
({:actor/first-name "ADAM" :actor/last-name "HOPPER"}
{:actor/first-name "ADAM" :actor/last-name "GRANT"})
{[[] {:order-by [:actor/first-name [:actor/last-name :desc]]
:limit 2}]
[:actor/first-name :actor/last-name]})

; :eql.mode/strict syntax
(heql/query
db-adapter
'[{([] {:order-by [:actor/first-name [:actor/last-name :desc]]
:limit 2})
[:actor/first-name :actor/last-name]}])

```

We can sort the relationship query results as well.

```clojure
; sorting one-to-many relationship query results

; :eql.mode/lenient syntax
(heql/query
db-adapter
{[:country/country-id 2]
[:country/country
; sorting `:country/cities` by `:city/city` in descending order
{[:country/cities {:order-by [[:city/city :desc]]}]
[:city/city]}]})

; :eql.mode/strict syntax
(heql/query
db-adapter
'{[:country/country-id 2]
[:country/country
; sorting `:country/cities` by `:city/city` in descending order
{(:country/cities {:order-by [[:city/city :desc]]})
[:city/city]}]})
'[{[:country/country-id 2]
[:country/country
; sorting `:country/cities` by `:city/city` in descending order
{(:country/cities {:order-by [[:city/city :desc]]})
[:city/city]}]}])
```

```clojure
; sorting many-to-many relationship query results

; :eql.mode/lenient syntax
(heql/query
db-adapter
{[:actor/actor-id 148]
[:actor/first-name
; sorting `:actor/films` by `:film/title` in descending order
{[:actor/films {:order-by [[:film/title :desc]]}]
[:film/title]}]})

; :eql.mode/strict syntax
(heql/query
db-adapter
'{[:actor/actor-id 148]
[:actor/first-name
; sorting `:actor/films` by `:film/title` in descending order
{(:actor/films {:order-by [[:film/title :desc]]})
[:film/title]}]})
'[{[:actor/actor-id 148]
[:actor/first-name
; sorting `:actor/films` by `:film/title` in descending order
{(:actor/films {:order-by [[:film/title :desc]]})
[:film/title]}]}])
```

> **NOTE:** Currently, sorting the relationship query results is not supported in MySQL
Expand Down

0 comments on commit 277e270

Please sign in to comment.