Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shows incorrect count number by using selectRelationCount previewFeatures #8050

Closed
Tracked by #8628
ikramhasib007 opened this issue Jul 4, 2021 · 6 comments · Fixed by prisma/prisma-engines#2143
Closed
Tracked by #8628
Assignees
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: previewFeatures Issue touches on an preview feature flag topic: selectRelationCount
Milestone

Comments

@ikramhasib007
Copy link

ikramhasib007 commented Jul 4, 2021

I have a list of posts and each post has multiple comments. I was counting the total comments that each post has. Using selectRelationCount previewFeatures, its count number is correct but it shows different references. like:
post id 1 has 2 comments
post id 2 has 4 comments
post id 3 has 0 comment
post id 4 has 0 comment

query result shows:
post id 1 has 0 comments
post id 2 has 0 comments
post id 3 has 4 comment
post id 4 has 2 comment

Query:

 ..
 select: {
      ...select.select.posts.select,
      _count: {
        select: { comments: true }
      }
    }
 .
 .
 const posts = await prisma.post.findMany(opArgs);
@janpio janpio added topic: selectRelationCount bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. kind/bug A reported bug. team/client Issue for team Client. labels Jul 4, 2021
@matthewmueller
Copy link
Contributor

Hey @ikramhasib007, can you share an example schema and script so we can reproduce?

@matthewmueller matthewmueller added the topic: previewFeatures Issue touches on an preview feature flag label Jul 6, 2021
@ikramhasib007
Copy link
Author

ikramhasib007 commented Jul 6, 2021

schema.prisma File

model User {
  id        String  @id       @default(cuid())
  name      String
  email     String  @unique
  password  String?
  posts     Post[]
  comments  Comment[]
  createdAt DateTime          @default(now())
  updatedAt DateTime          @updatedAt

  @@index([name, email])
}

model Post {
  id        String  @id       @default(cuid())
  title     String
  body      String
  published Boolean
  author    User              @relation(fields: [authorId], references: [id])
  authorId  String
  comments  Comment[]
  createdAt DateTime          @default(now())
  updatedAt DateTime          @updatedAt

  @@index([title])
}

model Comment {
  id        String  @id       @default(cuid())
  text      String
  post      Post              @relation(fields: [postId], references: [id])
  postId    String       
  author    User              @relation(fields: [authorId], references: [id])
  authorId  String
  createdAt DateTime          @default(now())
  updatedAt DateTime          @updatedAt
}

schema.graphql File

type Query {
  posts(query: String, skip: Int, take: Int, cursor: String): [Post!]!
  feed(query: String, take: Int, cursor: String): Feed
  comments(skip: Int, take: Int, cursor: String): [Comment!]!
}

type User {
  id: ID!
  name: String!
  email: String
  password: String
  posts(
    query: String
    cursor: String
    take: Int
    skip: Int
  ): [Post!]!
  comments(
    cursor: String
    take: Int
    skip: Int
  ): [Comment!]!
  createdAt: String!
  updatedAt: String!
}

type Post {
  id: ID!
  title: String!
  body: String!
  published: Boolean!
  author: User!
  comments(
    cursor: String
    take: Int
    skip: Int
  ): [Comment!]!
  createdAt: String!
  updatedAt: String!
  _count: Count
}

type Comment {
  id: ID!
  text: String!
  author: User!
  post: Post!
  createdAt: String!
  updatedAt: String!
}

type Count {
  comments: Int
}

type Feed {
  hasNextPage: Boolean
  posts(
    query: String
    cursor: String
    take: Int
    skip: Int
  ): [Post!]!
}

Queries resolvers

import { PrismaSelect } from '@paljs/plugins'
.
.

async feed(parent, args, { prisma }, info) {
    const select = new PrismaSelect(info).value
    try {
      const opArgs = {
        take: args.take ? args.take + 1 : 5 + 1,
        where: {
          published: true
        },
        orderBy: {
          createdAt: 'desc'
        },
        select: {
          ...select.select.posts.select
        }
      }
      if(typeof args.cursor === 'string') {
        opArgs.cursor = {
          id: args.cursor
        }
      }
      if(args.query) {
        opArgs.where.OR = [{
          title: {
            contains: args.query
          }
        }, {
          body: {
            contains: args.query
          }
        }]
      }
      if(opArgs.cursor) {
        opArgs.skip = 1
      }
      const posts = await prisma.post.findMany(opArgs);
      const feed = {
        hasNextPage: posts.length === opArgs.take,
        posts: posts.length === opArgs.take ? posts.slice(0, -1) : posts
      }
      return feed;
    } catch (error) {
      throw error
    }
  },

package.json

"dependencies": {
    "@apollo/client": "^3.3.15",
    "@babel/polyfill": "^7.12.1",
    "@graphql-tools/graphql-file-loader": "^6.2.7",
    "@graphql-tools/load": "^6.2.8",
    "@graphql-tools/schema": "^7.1.5",
    "@paljs/plugins": "^3.6.0",
    "@prisma/client": "^2.26.0",
    "bcryptjs": "^2.4.3",
    "cross-fetch": "^3.0.6",
    "cuid": "^2.1.8",
    "env-cmd": "^10.1.0",
    "express": "^4.17.1",
    "faker": "^5.4.0",
    "graphql": "^15.5.0",
    "graphql-postgres-subscriptions": "^1.0.5",
    "graphql-subscriptions": "^1.2.1",
    "graphql-yoga": "^1.18.3",
    "http-errors": "^1.8.0",
    "jsonwebtoken": "^8.5.1",
    "mkdirp": "^1.0.4",
    "nanoid": "^3.1.23",
    "pg": "^8.6.0",
    "subscriptions-transport-ws": "^0.9.19"
  },
  "devDependencies": {
    "@babel/cli": "^7.12.16",
    "@babel/core": "^7.12.16",
    "@babel/node": "^7.12.16",
    "@babel/plugin-proposal-object-rest-spread": "^7.12.13",
    "@babel/preset-env": "^7.12.16",
    "@babel/register": "^7.13.8",
    "jest": "^26.6.3",
    "nodemon": "^2.0.7",
    "prisma": "^2.26.0"
  }

@matthewmueller , check out the source code.
Note: normal queries are ok for relational counts. But when use cursor & skip for pagination then that incorrect count number happens.

@janpio janpio added bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. and removed bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. labels Jul 16, 2021
@oceandrama
Copy link

oceandrama commented Aug 6, 2021

Have the similar problem here, even without using skip or cursor

Schema:

datasource db {
  provider = "postgres"
  url      = env("DATABASE_URL")
}

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["nApi", "referentialActions", "selectRelationCount"]
}

enum UserRole {
  USER
  ADMIN
}

model User {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  name           String
  email          String   @unique
  hashedPassword String?
  role           UserRole @default(USER)

  authoredEvents Event[]
  participations Participant[]
}

model City {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  name String

  locations Location[]
}

model Location {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  name        String
  description String?
  coordinates Int[]

  city   City    @relation(fields: [cityId], references: [id])
  cityId Int
  events Event[]
}

enum GroupRole {
  PACER
  PARTICIPANT
}

enum ParticipationStatus {
  REGISTERED
  STARTED
  FINISHED
}

model Participant {
  createdAt DateTime @default(now())

  role   GroupRole
  status ParticipationStatus @default(REGISTERED)

  group   Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
  groupId Int
  user    User  @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId  Int

  @@id([groupId, userId])
}

model Group {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  pace      String
  startTime DateTime @db.Time
  limit     Int?

  event        Event         @relation(fields: [eventId], references: [id], onDelete: Cascade)
  eventId      Int
  participants Participant[]
}

model Event {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  distance    Int
  description String?
  startDate   DateTime @db.Date

  location   Location @relation(fields: [locationId], references: [id])
  locationId Int
  author     User?    @relation(fields: [authorId], references: [id])
  authorId   Int?
  groups     Group[]
}

Query:

db.event.findMany({
  select: {
    id: true,
    groups: {
      select: {
        id: true,
        participants: true,
        _count: {
          select: {
            participants: true,
          },
        },
      },
    },
  },
})

Result (attention to groups with id 12 and 14):

[
  {
    "id": 5,
    "groups": [
      {
        "id": 11,
        "participants": [
          {
            "createdAt": "2021-08-06T12:42:16.807Z",
            "role": "PARTICIPANT",
            "status": "REGISTERED",
            "groupId": 11,
            "userId": 1
          }
        ],
        "_count": {
          "participants": 1
        }
      },
      {
        "id": 12,
        "participants": [],
        "_count": {
          "participants": 1
        }
      },
      {
        "id": 10,
        "participants": [],
        "_count": {
          "participants": 0
        }
      }
    ]
  },
  {
    "id": 6,
    "groups": [
      {
        "id": 14,
        "participants": [
          {
            "createdAt": "2021-08-05T21:52:26.548Z",
            "role": "PARTICIPANT",
            "status": "REGISTERED",
            "groupId": 14,
            "userId": 1
          }
        ],
        "_count": {
          "participants": 0
        }
      },
      {
        "id": 13,
        "participants": [],
        "_count": {
          "participants": 0
        }
      }
    ]
  }
]

@pantharshit00
Copy link
Contributor

Thanks for the details, I can reproduce this now.

Posted minimal reproduction here: https://github.com/harshit-test-org/prisma-issue-8050

@pantharshit00 pantharshit00 removed their assignment Aug 9, 2021
@pantharshit00 pantharshit00 added bug/2-confirmed Bug has been reproduced and confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Aug 9, 2021
@matthewmueller matthewmueller added this to the 2.30.0 milestone Aug 11, 2021
@mart2967
Copy link

mart2967 commented Sep 5, 2021

I'm seeing this happen on 2.30.3 - have tried removing where, skip / take, orderBy, without success. Counts and length of selected relations don't match.

db.entity.findMany({
       where: { relatedEntity: { otherRelatedEntity: { id } } }
       skip,
        take,
        orderBy: { createdAt: 'desc' },
        select: {
          id: true,
          singleRelation: {
            select: {
              // returns array with correct length
              ManyRelation: {
                select: {
                  id: true
                }
              },
              // This returns correct counts attributed to the wrong rows
              _count: {
                 select: {
                   ManyRelation: true
                 }
               }
            }
          }
        }
      })

@janpio
Copy link
Member

janpio commented Sep 5, 2021

Can you open a separate issue please @mart2967 and provide all the information the issue template asks for? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: previewFeatures Issue touches on an preview feature flag topic: selectRelationCount
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants