【问题标题】:prisma Order by relation has only _count property. Can not order by relation fieldsprisma 按关系排序只有 _count 属性。不能按关系字段排序
【发布时间】:2021-08-28 01:00:52
【问题描述】:

考虑以下 Prisma 架构:

model Conversation {
  id           Int                         @id @default(autoincrement())
  createdAt    DateTime                    @db.Timestamp(6)
  messages     ConversationMessage[]
}

model ConversationMessage {
  id             Int                     @id @default(autoincrement())
  text           String                  @db.VarChar(1000)
  sentAt         DateTime                @map("sent_at") @db.Timestamp(6)
  conversationId Int?                    @map("conversation_id")
  userId         Int?                    @map("user_id")
  conversation   Conversation?           @relation(fields: [conversationId], references: [id])
  sender         User?                   @relation(fields: [userId], references: [id])
}

我想运行这样的查询,以便获得按消息日期排序的会话列表,即首先有新消息的会话。

prisma.conversation.findMany({
    orderBy: {
        messages: {
            sentAt: 'desc'
        }
    },
    ...
})

但我现在可以查询的唯一方法是这样,即关系在某种程度上只有_count 属性。

prisma.conversation.findMany({
    orderBy: {
        messages: {
           '_count': 'desc'
        }
     },
     ...
})

环境和设置


    OS: Mac OS,
    Database: PostgreSQL
    Node.js version: v12.19.0

棱镜版本

prisma               : 2.24.1
@prisma/client       : 2.24.1
Current platform     : darwin
Query Engine         : query-engine 18095475d5ee64536e2f93995e48ad800737a9e4 (at node_modules/@prisma/engines/query-engine-darwin)
Migration Engine     : migration-engine-cli 18095475d5ee64536e2f93995e48ad800737a9e4 (at node_modules/@prisma/engines/migration-engine-darwin)
Introspection Engine : introspection-core 18095475d5ee64536e2f93995e48ad800737a9e4 (at node_modules/@prisma/engines/introspection-engine-darwin)
Format Binary        : prisma-fmt 18095475d5ee64536e2f93995e48ad800737a9e4 (at node_modules/@prisma/engines/prisma-fmt-darwin)
Default Engines Hash : 18095475d5ee64536e2f93995e48ad800737a9e4
Studio               : 0.397.0
Preview Features     : orderByRelation

谢谢!

【问题讨论】:

    标签: sql postgresql prisma prisma2


    【解决方案1】:

    虽然 Prisma V2.19 引入了 sort by relation aggregate value,但在撰写本文时,唯一支持的聚合属性是 count。据我所知,目前 Prisma 不直接支持您的要求。如果他们添加 minmax 聚合属性进行排序,这是可能的。

    一种可能的解决方法是在检索后对 Node.js 中的消息进行排序。我正在添加一个解决方案,该解决方案使用orderByRelation 预览功能来简化排序并确保对话中的消息始终按顺序排列(最新消息在前)。

    更新 Prisma 客户端以使用 orderByRelation 预览功能。

    首先更新schema.prisma添加预览功能

    generator client {
      provider = "prisma-client-js"
      previewFeatures = ["orderByRelation"]
    }
    

    现在更新 prisma 客户端

    prisma generate client   
    

    获取conversations 并按最新消息对其进行排序

    // Assuming inside an async function 
    
    let unsortedConversations = await prisma.conversation.findMany({
        include: {
            messages: {
                orderBy: {    
                    sentAt: 'desc'  // messages for each converastion will be ordered newest first. 
                }
            }
        },
        // other conditions
    })
    
    

    unsortedConversations 包含所有必需的对话,但它们是无序的。您可以通过创建自定义比较器函数按所需顺序对其进行排序。

    function conversationComparatorFunction(conversationA, conversationB) {
        // Conversations with 0 messages will be placed last in arbitrary order. 
        if (!conversationB.messages.length) return 1;  
        if (!conversationA.messages.length) return -1;
        
        // sort conversations based on sentAt date of the first message. 
        // since messages were previously sorted, messages[0] always contain the most recent message. 
        if (conversationA.messages[0].sentAt > conversationB.messages[0].sentAt) {
            return -1;
        } else if (conversationA.messages[0].sentAt < conversationB.messages[0].sentAt) {
            return 1;
        } else return 0;
    
    }
    
    let sortedConversations = unsortedConversations.sort(conversationComparatorFunction)
    

    但请注意,如果 Conversation 记录的数量非常在应用程序端排序可能会导致性能下降,尤其是考虑到 Node.js 是单线程的。

    【讨论】:

    • 谢谢!我同样解决了这个问题,但在客户端添加了排序。
    【解决方案2】:

    如果启用此预览功能,现在可以按一对多关系排序:

    One-to-Many
    For one-to-many relationships, you can order by the relation from one side:
    
    ✅ Order posts by their author's name
    
    ⛔️ Order authors by their post's titles
    
    model Author {
      id Int @id
      name String
      posts Post[]
    }
    
    model Post {
      id Int @id
      title String
      author Author
    }
    prisma.post.findMany({
      orderBy: [{
        author: {
          name: 'asc'
        }
      }]
    })
    

    https://github.com/prisma/prisma/issues/5008

    【讨论】:

      【解决方案3】:

      OrderBy 关系仍然是一个预览功能 - 您需要确保使用功能标志

      generator client {
        provider        = "prisma-client-js"
        previewFeatures = ["orderByRelation"]
      }
      

      https://www.prisma.io/docs/concepts/components/prisma-client/filtering-and-sorting#sort-by-relation-preview

      【讨论】:

        猜你喜欢
        • 2018-01-07
        • 1970-01-01
        • 2013-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-03
        • 2019-04-12
        • 1970-01-01
        相关资源
        最近更新 更多