【问题标题】:Getting meta information from many-to-many table in Prisma从 Prisma 中的多对多表中获取元信息
【发布时间】:2021-06-20 14:23:17
【问题描述】:

我有这个表结构

注意item_level

我需要完成的是拥有相同的物品,连接到许多玩家,但每个玩家都可以独立升级物品。

这是我能想到的最简单的结构,用 sql 术语来说,连接表、选择字段并显示这些连接很容易。

我的问题是,我正在使用 Apollo graphql 和 Prisma ORM (v ^2.18.0),即使我可以得到每个玩家的物品,但我也可以-versa,我不知道如何包含那个额外的字段。

prisma.schema

model Player {
    id      Int              @id @default(id())
    items   ItemToPlayer[]
}

model Item {
    id      Int              @id @default(id())
    players ItemToPlayer[]
}

model ItemToPlayer {
    player      Player  @relation(fields: [playerId], references: [id])
    playerId    Int
    item        Item    @relation(fields: [itemId], references: [id])
    itemId      Int
    itemLevel   Int     @default(0)

    @@id([playerId, itemId])
}

类型定义

const typeDefs = gql`
    type Player {
        id: ID!
        items: [Item]
    }

    type Item {
        id: ID!
        players: [Player]
    }

    type ItemToPlayer {
        playerId: Int!
        itemId: Int!
        itemLevel: Int!
    }
`;

解析器

const resolvers = {
    Player: {
        items: (parent, args, context, info) => {
            return context.db.item.findMany({
                where: {
                    players: {
                        some: {
                            playerId: parent.id
                        }
                    }
                },
                include: {
                    players: true
                }
            });
        },
    },

    Item: {
        players: (parent, args, context, info) => {
            return context.db.player.findMany({
                where: {
                    items: {
                        some: {
                            itemId: parent.id
                        }
                    }
                },
                include: {
                    items: true
                }
            });
        },
    },

    Query: { /* ... */ },

    Mutation: {  /* ... */ },
};

这是我在查询玩家包括他们的物品时想要得到的结果

{
    "data": {
        "players": [
            {
                "id": 1
                "items": [
                    {
                        "id": 1,
                        "itemLevel": 2 // <--- This is missing 
                    },
                    {
                        "id": 2,
                        "itemLevel": 3
                    },
                ]
            },
            {
                "id": 2
                "items": [
                    {
                        "id": 1,
                        "itemLevel": 0 // same item (id: 1) has different level per player
                    }
                ]
            },
        ]
    }
}

documentation 中,它将此描述为显式多对多关系,并提到

请注意,适用与 1-n 关系相同的规则(因为 Post↔ CategoriesOnPosts 和 Category ↔ CategoriesOnPosts 实际上都是 1-n-relations),这意味着关系的一侧需要是 使用@relation 属性进行注释。

但它没有提供示例。

进一步研究1-n-relations@relation,我发现的唯一示例是外键。

在 Internet 上搜索时,我发现其他人就不同的框架和 ORM 提出相同的问题,但没有找到 Prisma。 (除非我错过了

【问题讨论】:

    标签: graphql apollo prisma


    【解决方案1】:

    我建议将您的 typedef 更改为:

    const typeDefs = gql`
        type Player {
            id: ID!
            items: [ItemToPlayer]
        }
    
        type Item {
            id: ID!
            players: [ItemToPlayer]
        }
    
        type ItemToPlayer {
            playerId: Int!
            itemId: Int!
            itemLevel: Int!
            player: Player!
            item: Item!
        }
    `;
    

    然后Item 中的players 解析器将如下所示:

    prisma.player.findMany({
        where: {
          items: {
            some: {
              itemId: parent.id,
            },
          },
        },
        include: {
          items: { include: { item: true } },
        },
    })
    

    【讨论】:

    • 将 typeDefs 更改为 ItemToPlayer 而不是 Item 有帮助,因为我可以在 db 中查询 itemToPlayer,然后在结果中查询 Item。嵌套的include 给了我一个错误。我设法在没有嵌套包含的情况下做到了。不过,我确实必须修改查询本身。
    【解决方案2】:

    正如@Ryan 在他的回答中建议的那样,我设法通过将Item 更改为ItemToPlayer 并更改我的查询和解析器来获取元数据。

    新的Item解析器

    Item: {
        players: (parent, args, context, info) => {
            return context.db.itemToPlayer.findMany({
                where: {
                    itemId: parent.id
                },
                include: {
                    item: true
                }
            });
        },
    },
    

    我现在正在查询ItemsToPlayers 表并取回ItemToPlayer 类型,然后我可以从中查询Item

    CORRECT
    query {
      players {
        id
        items {
          id
          itemLevel
          item {
            id
          }
        }
      }
    }
    
    WRONG
    query {
      players {
        id
        items {
          id
          itemLevel <--- This is wrong as itemLevel
                                        does not exist in Item
        }
      }
    }
    

    结果

    {
        "data": {
            "players": [
                {
                    "id": 1
                    "items": [
                        {
                            "itemLevel": 2
                            "item": {
                                 "id": 1,
                            }
                        },
                        {
                            "itemLevel": 0
                            "item": {
                                 "id": 1,
                            }
                        },
                    ]
                },
            ]
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-08-04
      • 2012-03-13
      • 2023-03-25
      • 1970-01-01
      • 2011-01-05
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多