rmosolgo / graphql-ruby

Ruby implementation of GraphQL
http://graphql-ruby.org
MIT License
5.37k stars 1.38k forks source link

Can't get total count of connection (excluding pagination) #2829

Closed nicolasrouanne closed 4 years ago

nicolasrouanne commented 4 years ago

Describe the bug

When trying to get the total_count of a connection, I get only the number of results filtered by the pagination, not the number of objects in the connection.

Versions

graphql: 1.10.3 rails : 6.0.2.1 graphql-batch: 0.4.2

GraphQL schema

class Types::BaseConnection < GraphQL::Types::Relay::BaseConnection
  field :total_count, Integer, null: false

  def total_count
    object.nodes&.count
  end
end

class Types::BaseObject < GraphQL::Schema::Object
  field_class Types::BaseField
  connection_type_class BaseConnection
end

class Types::QueryType < Types::BaseObject
  add_field(GraphQL::Types::Relay::NodeField)
  field :users, UserType.connection_type, null: false

  def users
    User.all
  end
end

class ApiSchema < GraphQL::Schema
  query(Types::QueryType)

  # Opt in to the new runtime (default in future graphql-ruby versions)
  use GraphQL::Execution::Interpreter
  use GraphQL::Analysis::AST

  # Add built-in connections for pagination
  use GraphQL::Pagination::Connections
end

GraphQL query When querying with no pagination parameters, I get the correct amount of objects in totalCount, i.e. all the objects

query {
    users {
        totalCount
        nodes {
            id
        }
    }
}
{
    "data": {
        "users": {
            "totalCount": 5,
            "nodes": [
                {
                    "id": "U2FpbG9yLTI="
                },
                {
                    "id": "U2FpbG9yLTM="
                },
                {
                    "id": "U2FpbG9yLTQ="
                },
                {
                    "id": "U2FpbG9yLTc="
                },
                {
                    "id": "U2FpbG9yLTEw"
                }
            ]
        }
    }
}

When passing pagination parameters the totalCount doesn't reflect the entire connection, rather the current page

query {
    users(first: 2) {
        totalCount
        nodes {
            id
        }
    }
}
{
    "data": {
        "users": {
            "totalCount": 2,
            "nodes": [
                {
                    "id": "U2FpbG9yLTI="
                },
                {
                    "id": "U2FpbG9yLTM="
                }
            ]
        }
    }
}

Expected behavior

I expected total_count to return the total number of items in the connection, as pointed out in that wiki article

Actual behavior

It only returns the number of items in a page.

rmosolgo commented 4 years ago

Thanks for opening this issue -- that doc is out-of-date, and I haven't written a better replacement yet 😖 . In the new pagination system in 1.10+, the methods of connection objects have changed.

So, you code could be updated like this:

  def total_count
+   object.items&.count
-   object.nodes&.count
  end

Does that work for you?

Let's keep this open til I fix that doc.

nicolasrouanne commented 4 years ago

Using object.items&.count works perfectly! 😃🎉 Thanks for the quick reply 🙏

I would find it very useful indeed to know more generally what are the available methods to call (be it in Types, Connection, Edge, etc.). For instance, knowing that you can access object or items is not very easy to find, as you say.

It would be great if that could be added to the guides, which I find very useful and readable compared to the RubyDoc 🙈

codefist commented 3 years ago

total_count should be there by default

angeloocana commented 2 years ago

object.items.size is not working for me anymore, I get the error:

undefined method `items' for #<GraphQL::Pro::RelationConnection::OrderedRelationConnection:0x00007efc2fd66ff0 
rmosolgo commented 2 years ago

Hey @angeloocana, could you please open a new issue (https://github.com/rmosolgo/graphql-ruby/issues/new/choose) for the problem you encountered? I'd like to understand what you were working on (or what else changed) when your code stopped working for you, but it looks like your situation is a bit different than the one described here last year.