dialect/sql/sqljson: support for order by value and length (#3278)

This commit is contained in:
Ariel Mashraki
2023-01-26 12:20:31 +02:00
committed by GitHub
parent 604c4942a4
commit 433609444c
6 changed files with 258 additions and 81 deletions

View File

@@ -1,69 +0,0 @@
---
id: paging
title: Paging And Ordering
---
## Limit
`Limit` limits the query result to `n` entities.
```go
users, err := client.User.
Query().
Limit(n).
All(ctx)
```
## Offset
`Offset` sets the first node to return from the query.
```go
users, err := client.User.
Query().
Offset(10).
All(ctx)
```
## Ordering
`Order` returns the entities sorted by the values of one or more fields. Note that, an error
is returned if the given fields are not valid columns or foreign-keys.
```go
users, err := client.User.Query().
Order(ent.Asc(user.FieldName)).
All(ctx)
```
## Edge Ordering
In order to sort by fields of an edge (relation), start the traversal from the edge (you want to order by),
apply the ordering, and then jump to the neighbours (target type).
The following shows how to order the users by the `"name"` of their `"pets"` in ascending order.
```go
users, err := client.Pet.Query().
Order(ent.Asc(pet.FieldName)).
QueryOwner().
All(ctx)
```
## Custom Ordering
Custom ordering functions can be useful if you want to write your own storage-specific logic.
The following shows how to order pets by their name, and their owners' name in ascending order.
```go
names, err := client.Pet.Query().
Order(func(s *sql.Selector) {
// Join with user table for ordering by owner-name and pet-name.
t := sql.Table(user.Table)
s.Join(t).On(s.C(pet.OwnerColumn), t.C(user.FieldID))
s.OrderBy(t.C(user.FieldName), s.C(pet.FieldName))
}).
Select(pet.FieldName).
Strings(ctx)
```

138
doc/md/paging.mdx Normal file
View File

@@ -0,0 +1,138 @@
---
id: paging
title: Paging And Ordering
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## Limit
`Limit` limits the query result to `n` entities.
```go
users, err := client.User.
Query().
Limit(n).
All(ctx)
```
## Offset
`Offset` sets the first node to return from the query.
```go
users, err := client.User.
Query().
Offset(10).
All(ctx)
```
## Ordering
`Order` returns the entities sorted by the values of one or more fields. Note that, an error
is returned if the given fields are not valid columns or foreign-keys.
```go
users, err := client.User.Query().
Order(ent.Asc(user.FieldName)).
All(ctx)
```
## Edge Ordering
In order to sort by fields of an edge (relation), start the traversal from the edge (you want to order by),
apply the ordering, and then jump to the neighbours (target type).
The following shows how to order the users by the `"name"` of their `"pets"` in ascending order.
```go
users, err := client.Pet.Query().
Order(ent.Asc(pet.FieldName)).
QueryOwner().
All(ctx)
```
## Custom Ordering
Custom ordering functions can be useful if you want to write your own storage-specific logic.
The following shows how to order pets by their name, and their owners' name in ascending order.
```go
names, err := client.Pet.Query().
Order(func(s *sql.Selector) {
// Join with user table for ordering by owner-name and pet-name.
t := sql.Table(user.Table)
s.Join(t).On(s.C(pet.OwnerColumn), t.C(user.FieldID))
s.OrderBy(t.C(user.FieldName), s.C(pet.FieldName))
}).
Select(pet.FieldName).
Strings(ctx)
```
#### Order by JSON fields
The [`sqljson`](https://pkg.go.dev/entgo.io/ent/dialect/sql/sqljson) package allows to easily sort data based on the
value of a JSON object:
<Tabs>
<TabItem value="value" label="By Value" default>
```go {3}
users := client.User.Query().
Order(
sqljson.OrderValue(user.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
```
</TabItem>
<TabItem value="length" label="By Length">
```go {3}
users := client.User.Query().
Order(
sqljson.OrderLen(user.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
```
</TabItem>
<TabItem value="desc" label="Descending">
```go {3,9}
users := client.User.Query().
Order(
sqljson.OrderValueDesc(user.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
pets := client.Pet.Query().
Order(
sqljson.OrderLenDesc(pet.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
```
</TabItem>
</Tabs>
<details>
<summary>PostgreSQL limitation on <code>ORDER BY</code> expressions with <code>SELECT DISTINCT</code></summary>
<div>
PostgreSQL does not support `ORDER BY` expressions with `SELECT DISTINCT`. Thus, the `Unique` modifier should be set
to `false`. However, keep in mind that this may result in duplicate results when performing graph traversals.
```diff
users := client.User.Query().
Order(
sqljson.OrderValue(user.FieldData, sqljson.Path("key1", "key2")),
).
+ Unique(false).
AllX(ctx)
```
</div>
</details>