README.md in graphql-groups-0.1.1 vs README.md in graphql-groups-0.1.2
- old
+ new
@@ -1,47 +1,49 @@
# GraphQL Groups
+[![Gem Version](https://badge.fury.io/rb/graphql-groups.svg)](https://badge.fury.io/rb/graphql-groups)
[![Build Status](https://github.com/hschne/graphql-groups/workflows/Build/badge.svg)](https://github.com/hschne/graphql-groups/workflows/Build/badge.svg)
[![Maintainability](https://api.codeclimate.com/v1/badges/692d4125ac8548fb145e/maintainability)](https://codeclimate.com/github/hschne/graphql-groups/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/692d4125ac8548fb145e/test_coverage)](https://codeclimate.com/github/hschne/graphql-groups/test_coverage)
-Create flexible and performant aggregation queries with [graphql-ruby](https://github.com/rmosolgo/graphql-ruby)
+Statistics and aggregates built on top of [graphql-ruby](https://github.com/rmosolgo/graphql-ruby).
## Installation
-Add this line to your application's Gemfile and execute bundler.
+Add this line to your application's Gemfile and run `bundle install`.
```ruby
gem 'graphql-groups'
```
```bash
$ bundle install
```
## Usage
-Create a new group type to specify which attributes you wish to group by inheriting from `GraphQL::Groups::GroupType`
+Create a new group type to specify which attributes you wish to group by inheriting from `GraphQL::Groups::GroupType`:
```ruby
class AuthorGroupType < GraphQL::Groups::GroupType
scope { Author.all }
+ by :name
by :age
end
```
-Include the new type in your schema using the `group` keyword.
+Include the new type in your schema using the `group` keyword, and you are done.
```ruby
-class QueryType < BaseType
+class QueryType < GraphQL::Schema::Object
include GraphQL::Groups
group :author_groups, AuthorGroupType
end
```
-You can then run an aggregation query for this grouping.
+You can then run a query to retrieve statistical information about your data, for example the number of authors per age.
```graphql
query myQuery{
authorGroups {
age {
@@ -65,18 +67,78 @@
},
...
]
}
}
-
```
+## Why?
+
+`graphql-ruby` lacks a built in way to query statistical data of collections. It is possible to add this functionality by
+using `group_by` (see for example [here](https://dev.to/gopeter/how-to-add-a-groupby-field-to-your-graphql-api-1f2j)),
+but this performs poorly for large amounts of data.
+
+`graphql-groups` allows you to write flexible, readable queries while leveraging your database to group and
+aggregate data. See [performance](#Performance) for a benchmark.
+
## Advanced Usage
+#### Grouping by Multiple Attributes
+
+This library really shines when you want to group by multiple attributes, or otherwise retrieve complex statistical information
+within a single GraphQL query.
+
+For example, to get the number of authors grouped by their name, and then also by age, you could construct a query similar to this:
+
+```graphql
+query myQuery{
+ authorGroups {
+ name {
+ key
+ count
+ groupBy {
+ age {
+ key
+ count
+ }
+ }
+ }
+ }
+}
+```
+
+```json
+{
+ "authorGroups":{
+ "name":[
+ {
+ "key":"Ada",
+ "count":2,
+ "groupBy": {
+ "age": [
+ {
+ "key":"30",
+ "count":1
+ },
+ {
+ "key":"35",
+ "count":1
+ }
+ ]
+ }
+ },
+ ...
+ ]
+ }
+}
+```
+
+`graphql-groups` will automatically execute the required queries and return the results in a easily parsable response.
+
#### Custom Grouping Queries
-To customize how items are grouped, you may specify the grouping query by creating a method of the same name in the group type.
+To customize which queries are executed to group items, you may specify the grouping query by creating a method of the same name in the group type.
```ruby
class AuthorGroupType < GraphQL::Groups::Schema::GroupType
scope { Author.all }
@@ -109,12 +171,37 @@
end
end
end
```
-For more examples see the [feature spec](./spec/graphql/feature_spec.rb) and [test schema](./spec/graphql/support/test_schema)
+When defining a group type's scope you may access the parents `object` and `context`.
+```ruby
+class QueryType < GraphQL::Schema::Object
+ field :statistics, StatisticsType, null: false
+
+ def statistics
+ Book.all
+ end
+end
+
+class StatisticsType < GraphQL::Schema::Object
+ include GraphQL::Groups
+
+ group :books, BookGroupType
+end
+
+class BookGroupType < GraphQL::Groups::Schema::GroupType
+ # `object` refers to `Book.all`
+ scope { object.where(author_id: context[:current_person]) }
+
+ by :name
+end
+```
+
+For more examples see the [feature spec](./spec/graphql/feature_spec.rb) and [test schema](./spec/graphql/support/test_schema.rb)
+
### Custom Aggregates
Per default `graphql-groups` supports aggregating `count` out of the box. If you need to other aggregates, such as sum or average
you may add them to your schema by creating a custom `GroupResultType`. Wire this up to your schema by specifying the result type in your
group type.
@@ -156,23 +243,39 @@
end
```
For more examples see the [feature spec](./spec/graphql/feature_spec.rb) and [test schema](./spec/graphql/support/test_schema)
+## Performance
+
+While it is possible to add grouping to your GraphQL schema by using `group_by` (see [above](#why)) this performs poorly for large amounts of data. The graph below shows the number of requests per second possible with both implementations.
+
+![benchmark](benchmark/benchmark.jpg)
+
+The benchmark queries the author count grouped by name, using an increasing number of authors. While the in-memory approach of grouping works well for a small number of records, it is outperformed quickly as that number increases.
+
+Benchmarks are generated using [benchmark-ips](https://github.com/evanphx/benchmark-ips). The benchmark script used to generate the report be found [here](./benchmark/benchmark.rb)
+
## Limitations and Known Issues
-*This gem is in early development!*. There are a number of issues that are still being addressed. There is no guarantee
-that this libraries API will not change fundamentally from one release to the next.
+*This gem is in early development!* There are a number of issues that are still being addressed. There is no guarantee
+that this libraries API will not change fundamentally from one release to the next. Please refer to the [issue tracker](https://github.com/hschne/graphql-groups/issues) for a list of known issues.
+## Credits
+
+![Meister](meister.png)
+
+graphql-groups is supported by and battle-tested at [Meister](https://www.meisterlabs.com/)
+
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
## Contributing
-Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/graphql-groups. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
+Bug reports and pull requests are welcome on GitHub at https://github.com/hschne/graphql-groups. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).