BoomDizzle
BoomDizzle

Reputation: 197

Aggregating fields in graphene/django queries

I am writing a graphene/django ORM query, where I need to aggregate the values of a particular field on all my query result objects and return it with the query. Not quite sure how to do that, as this involves some post-processing. Would appreciate it if someone can offer some guidance.

Here's some sample code. Django model class 'Market' has an integer field 'num_vendors'. The Graphene wrapper is 'MarketNode' that wraps around the 'Market' model class:

Model class:

class Market(models.Model):
       num_vendors = models.IntegerField(....)

Graphene class:

class MarketNode(DjangoObjectType):
   Meta:
      model: Market

I'd like the query to return 'market_count' (there are multiple markets) and 'vendor_count' (sum of all 'vendors' across all markets). So the query would look like:

allMarkets {
  market_count
  vendor_count
  edges {
    node {
      ...
      ...
      num_vendors
      ...
    }
  }
}

For the market_count, I am following this example (this works fine): https://github.com/graphql-python/graphene-django/wiki/Adding-counts-to-DjangoFilterConnectionField

For vendor_count (across all markets), I assume I need to iterate over the results and add all the num_vendors fields, after the query is complete and resolved. How can I achieve this? This must be a fairly common-use case, so I am sure graphene provides some hooks to do this.

Upvotes: 4

Views: 2226

Answers (1)

desert dog
desert dog

Reputation: 46

You can define MarketConnection with the count fields on it.

Something like:


class MarketConnection(graphene.relay.Connection):
    class Meta:
        node = Market

    market_count = graphene.Int(required=True)
    vendor_count = graphene.Int(required=True)

    def resolve_market_count(self, info, **kwargs):
        return self.iterable.count() if isinstance(self.iterable, QuerySet) else len(self.iterable)

    def resolve_vendor_count(self, info, **kwargs):
        if isinstance(self.iterable, QuerySet):
            return self.iterable.aggregate(Count("vendor"))
        return sum([market.num_vendors for market in self.iterable])

and add connection_class to your MarketNode

class MarketNode(DjangoObjectType):
   class Meta:
      model: Market
      connection_class: MarketConnection

Upvotes: 3

Related Questions