neo4j-graphql / neo4j-graphql-js

NOTE: This project is no longer actively maintained. Please consider using the official Neo4j GraphQL Library (linked in README).
Other
608 stars 148 forks source link

Feature Request: support standard GraphQL pagination #357

Open colinskow opened 4 years ago

colinskow commented 4 years ago

For pagination it is very useful to know the total number of records for a given query. I would like to have the augmented schema automatically generate a count query for each type.

Example:

{
  Employees(
    filter: { OR: [{ name_contains: "Mar" }, { email_contains: "Mar" }] }
    first: 10
    orderBy: [name_asc]
  ) {
    _id
    email
    name
  }
  EmployeesCount(
    filter: { OR: [{ name_contains: "Mar" }, { email_contains: "Mar" }] }
  )
}

See this thread for further discussion.

benjamin-rood commented 4 years ago

Do you want the total number of pages relative to the query, or just a query function on the total number of records which you can filter on? Because if it's the later I can write up how you can create this yourself as an interim solution.

colinskow commented 4 years ago

All I need is the total number of records which satisfy the query. The rest of the pagination is then very easy to calculate.

colinskow commented 4 years ago

Actually GraphQL has a published standard for handling pagination, and it would be best for the augmented schema to follow that exactly. https://graphql.org/learn/pagination/

AshkanHovold commented 4 years ago

I am looking for the same thing. We can have queries that return alot of data, and it would be nice to be able to get a count before you actually retrieve the data. Currently we are writing our own custom cypher queries for this, but it would be alot better if it could have been done with graphql syntax.

AdrienLemaire commented 4 years ago

Sorry if my comment is off-topic, I'm new to graphql and grandstack. AFAIK, there are 2 types of pagination supported by graphql, numbered pages and cursor-based. Apollo documentation also explains it nicely.

If I understand correctly, neo4j-graphql only supports numbered pages style first&offset pagination. Could we also get support for cursor-based pagination ?

JCMais commented 4 years ago

Anyone had success implementing this?

erik7z commented 3 years ago

https://grandstack.io/docs/graphql-filtering/ explains how to filter results. But how to get count of the query results ?

Pagination is quite basic requirement for any application. Is there any solution for this ?

erik7z commented 3 years ago

I've found one solution to have totalCount query while using auto-generated queries. Its a bit hacky, but works.

Lets say you have such type definition:

type Question  {
  nodeId: ID! @id
  title: String!
  text: String!
  totalCount: Int # will be used to implement total count on query resolver
}

And you can make such query type definition:

type Query {
    QuestionCount: Question  # only `totalCount` field will be actually resolved
}

Then create such custom query resolver:

import { cypherQuery } from 'neo4j-graphql-js'

const questionResolvers = {
        QuestionCount: async (_parent, params, context, resolveInfo) => {

             // generating querystring with all necessary filters and params
            const [queryString, queryParams] = cypherQuery(params, context, resolveInfo)

            // using neo4j-graphql driver injected in context to perform custom call
            const resultsCount = await context.driver
                .session()
                .run(queryString, queryParams)
                .then((res) => res.records.length) // getting count of the results

            const requiredFieldsMessage =
                '### Only `totalCount` field can be resolved with this query'

            return {
                nodeId: requiredFieldsMessage, // fields required in type definitions have to be resolved somehow
                title: requiredFieldsMessage, // fields required in type definitions have to be resolved somehow
                text: requiredFieldsMessage,// fields required in type definitions have to be resolved somehow
                totalCount: resultsCount, // <--- Here you get your results total count
            }
        },
}

After implementing above code you can query api with following graphql query:

query{
  Question(filter:{
    title_contains:"a" # your filters
  }){
    nodeId
    title
    text
  }
  QuestionCount(filter:{
    title_contains:"a" # <-- repeat your filters for count query
  }) {
      totalCount
    }
}

And you will get following result:

{
  "data": {
    "Question": [
      {
        "nodeId": "aeede919-4e01-4946-a13d-172702e4997a",
        "title": "Question containing 'a' letter 1",
        "text": "Question containing a letter 1"
      },
      {
        "nodeId": "5a17bd7c-74f9-4c64-ad7d-9f2675d31fe3",
        "title": "Question containing 'a' letter 2",
        "text": "Question containing 'a' letter 2"
      },
    ],
    "QuestionCount": {
      "totalCount": 2
    }
  }
}

I'm sure original neo4jgraphql() call to database also can return count() under the hood, but it is not so easy to get it out from there.

Any way, above solution works for me, hope it will help to you also.

chunkychode commented 3 years ago

@erik7z learned something new today so thanks for that :)

michaeldgraham commented 3 years ago

https://github.com/neo4j-graphql/neo4j-graphql-js/issues/608