add docs
This commit is contained in:
@ -1,15 +1,23 @@
|
||||
# Aggregation functions
|
||||
|
||||
Currently 2 aggregation functions are supported.
|
||||
Currently 6 aggregation functions are supported.
|
||||
|
||||
|
||||
* `count() -> int`
|
||||
* `exists() -> bool`
|
||||
* `sum(columns) -> Any`
|
||||
* `avg(columns) -> Any`
|
||||
* `min(columns) -> Any`
|
||||
* `max(columns) -> Any`
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.count()` method
|
||||
* `QuerysetProxy.exists()` method
|
||||
* `QuerysetProxy.sum(columns)` method
|
||||
* `QuerysetProxy.avg(columns)` method
|
||||
* `QuerysetProxy.min(column)` method
|
||||
* `QuerysetProxy.max(columns)` method
|
||||
|
||||
|
||||
## count
|
||||
@ -68,6 +76,209 @@ class Book(ormar.Model):
|
||||
has_sample = await Book.objects.filter(title='Sample').exists()
|
||||
```
|
||||
|
||||
## sum
|
||||
|
||||
`sum(columns) -> Any`
|
||||
|
||||
Returns sum value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||
|
||||
You can pass one or many column names including related columns.
|
||||
|
||||
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||
|
||||
You cannot `sum` non numeric columns.
|
||||
|
||||
If you aggregate on one column, the single value is directly returned as a result
|
||||
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||
|
||||
Given models like follows
|
||||
|
||||
```Python
|
||||
--8<-- "../docs_src/aggregations/docs001.py"
|
||||
```
|
||||
|
||||
A sample usage might look like following
|
||||
|
||||
```python
|
||||
author = await Author(name="Author 1").save()
|
||||
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||
|
||||
assert await Book.objects.sum("year") == 5773
|
||||
result = await Book.objects.sum(["year", "ranking"])
|
||||
assert result == dict(year=5773, ranking=9)
|
||||
|
||||
try:
|
||||
# cannot sum string column
|
||||
await Book.objects.sum("title")
|
||||
except ormar.QueryDefinitionError:
|
||||
pass
|
||||
|
||||
assert await Author.objects.select_related("books").sum("books__year") == 5773
|
||||
result = await Author.objects.select_related("books").sum(
|
||||
["books__year", "books__ranking"]
|
||||
)
|
||||
assert result == dict(books__year=5773, books__ranking=9)
|
||||
|
||||
assert (
|
||||
await Author.objects.select_related("books")
|
||||
.filter(books__year__lt=1925)
|
||||
.sum("books__year")
|
||||
== 3843
|
||||
)
|
||||
```
|
||||
|
||||
## avg
|
||||
|
||||
`avg(columns) -> Any`
|
||||
|
||||
Returns avg value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||
|
||||
You can pass one or many column names including related columns.
|
||||
|
||||
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||
|
||||
You cannot `avg` non numeric columns.
|
||||
|
||||
If you aggregate on one column, the single value is directly returned as a result
|
||||
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||
|
||||
```Python
|
||||
--8<-- "../docs_src/aggregations/docs001.py"
|
||||
```
|
||||
|
||||
A sample usage might look like following
|
||||
|
||||
```python
|
||||
author = await Author(name="Author 1").save()
|
||||
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||
|
||||
assert round(float(await Book.objects.avg("year")), 2) == 1924.33
|
||||
result = await Book.objects.avg(["year", "ranking"])
|
||||
assert round(float(result.get("year")), 2) == 1924.33
|
||||
assert result.get("ranking") == 3.0
|
||||
|
||||
try:
|
||||
# cannot avg string column
|
||||
await Book.objects.avg("title")
|
||||
except ormar.QueryDefinitionError:
|
||||
pass
|
||||
|
||||
result = await Author.objects.select_related("books").avg("books__year")
|
||||
assert round(float(result), 2) == 1924.33
|
||||
result = await Author.objects.select_related("books").avg(
|
||||
["books__year", "books__ranking"]
|
||||
)
|
||||
assert round(float(result.get("books__year")), 2) == 1924.33
|
||||
assert result.get("books__ranking") == 3.0
|
||||
|
||||
assert (
|
||||
await Author.objects.select_related("books")
|
||||
.filter(books__year__lt=1925)
|
||||
.avg("books__year")
|
||||
== 1921.5
|
||||
)
|
||||
```
|
||||
|
||||
## min
|
||||
|
||||
`min(columns) -> Any`
|
||||
|
||||
Returns min value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||
|
||||
You can pass one or many column names including related columns.
|
||||
|
||||
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||
|
||||
If you aggregate on one column, the single value is directly returned as a result
|
||||
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||
|
||||
```Python
|
||||
--8<-- "../docs_src/aggregations/docs001.py"
|
||||
```
|
||||
|
||||
A sample usage might look like following
|
||||
|
||||
```python
|
||||
author = await Author(name="Author 1").save()
|
||||
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||
|
||||
assert await Book.objects.min("year") == 1920
|
||||
result = await Book.objects.min(["year", "ranking"])
|
||||
assert result == dict(year=1920, ranking=1)
|
||||
|
||||
assert await Book.objects.min("title") == "Book 1"
|
||||
|
||||
assert await Author.objects.select_related("books").min("books__year") == 1920
|
||||
result = await Author.objects.select_related("books").min(
|
||||
["books__year", "books__ranking"]
|
||||
)
|
||||
assert result == dict(books__year=1920, books__ranking=1)
|
||||
|
||||
assert (
|
||||
await Author.objects.select_related("books")
|
||||
.filter(books__year__gt=1925)
|
||||
.min("books__year")
|
||||
== 1930
|
||||
)
|
||||
```
|
||||
|
||||
## max
|
||||
|
||||
`max(columns) -> Any`
|
||||
|
||||
Returns max value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||
|
||||
Returns min value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||
|
||||
You can pass one or many column names including related columns.
|
||||
|
||||
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||
|
||||
If you aggregate on one column, the single value is directly returned as a result
|
||||
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||
|
||||
```Python
|
||||
--8<-- "../docs_src/aggregations/docs001.py"
|
||||
```
|
||||
|
||||
A sample usage might look like following
|
||||
|
||||
```python
|
||||
author = await Author(name="Author 1").save()
|
||||
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||
|
||||
assert await Book.objects.max("year") == 1930
|
||||
result = await Book.objects.max(["year", "ranking"])
|
||||
assert result == dict(year=1930, ranking=5)
|
||||
|
||||
assert await Book.objects.max("title") == "Book 3"
|
||||
|
||||
assert await Author.objects.select_related("books").max("books__year") == 1930
|
||||
result = await Author.objects.select_related("books").max(
|
||||
["books__year", "books__ranking"]
|
||||
)
|
||||
assert result == dict(books__year=1930, books__ranking=5)
|
||||
|
||||
assert (
|
||||
await Author.objects.select_related("books")
|
||||
.filter(books__year__lt=1925)
|
||||
.max("books__year")
|
||||
== 1923
|
||||
)
|
||||
```
|
||||
|
||||
## QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||
@ -89,6 +300,26 @@ objects from other side of the relation.
|
||||
Works exactly the same as [exists](./#exists) function above but allows you to select columns from related
|
||||
objects from other side of the relation.
|
||||
|
||||
### sum
|
||||
|
||||
Works exactly the same as [sum](./#sum) function above but allows you to sum columns from related
|
||||
objects from other side of the relation.
|
||||
|
||||
### avg
|
||||
|
||||
Works exactly the same as [avg](./#avg) function above but allows you to average columns from related
|
||||
objects from other side of the relation.
|
||||
|
||||
### min
|
||||
|
||||
Works exactly the same as [min](./#min) function above but allows you to select minimum of columns from related
|
||||
objects from other side of the relation.
|
||||
|
||||
### max
|
||||
|
||||
Works exactly the same as [max](./#max) function above but allows you to select maximum of columns from related
|
||||
objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
|
||||
@ -289,7 +289,7 @@ books = (
|
||||
```
|
||||
|
||||
If you want or need to you can nest deeper conditions as deep as you want, in example to
|
||||
acheive a query like this:
|
||||
achieve a query like this:
|
||||
|
||||
sql:
|
||||
```
|
||||
@ -564,6 +564,38 @@ assert owner.toys[1].name == "Toy 1"
|
||||
|
||||
Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`
|
||||
|
||||
### Default sorting in ormar
|
||||
|
||||
Since order of rows in a database is not guaranteed, `ormar` **always** issues an `order by` sql clause to each (part of) query even if you do not provide order yourself.
|
||||
|
||||
When querying the database with given model by default the `Model` is ordered by the `primary_key`
|
||||
column ascending. If you wish to change the default behaviour you can do it by providing `orders_by`
|
||||
parameter to model `Meta` class.
|
||||
|
||||
!!!tip
|
||||
To read more about models sort order visit [models](../models/index.md#model-sort-order) section of documentation
|
||||
|
||||
By default the relations follow the same ordering, but you can modify the order in which related models are loaded during query by providing `orders_by` and `related_orders_by`
|
||||
parameters to relations.
|
||||
|
||||
!!!tip
|
||||
To read more about models sort order visit [relations](../relations/index.md#relationship-default-sort-order) section of documentation
|
||||
|
||||
Order in which order_by clauses are applied is as follows:
|
||||
|
||||
* Explicitly passed `order_by()` calls in query
|
||||
* Relation passed `orders_by` and `related_orders_by` if exists
|
||||
* Model `Meta` class `orders_by`
|
||||
* Model `primary_key` column ascending (fallback, used if none of above provided)
|
||||
|
||||
**Order from only one source is applied to each `Model` (so that you can always overwrite it in a single query).**
|
||||
|
||||
That means that if you provide explicit `order_by` for a model in a query, the `Relation` and `Model` sort orders are skipped.
|
||||
|
||||
If you provide a `Relation` one, the `Model` sort is skipped.
|
||||
|
||||
Finally, if you provide one for `Model` the default one by `primary_key` is skipped.
|
||||
|
||||
### QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||
|
||||
Reference in New Issue
Block a user