prisma 按关系排序只有 _count 属性。不能按关系字段排序
Posted
技术标签:
【中文标题】prisma 按关系排序只有 _count 属性。不能按关系字段排序【英文标题】:prisma Order by relation has only _count property. Can not order by relation fields 【发布时间】: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
谢谢!
【问题讨论】:
【参考方案1】:虽然 Prisma V2.19 引入了 sort by relation aggregate value,但在撰写本文时,唯一支持的聚合属性是 count
。据我所知,目前 Prisma 不直接支持您的要求。如果他们添加 min
和 max
聚合属性进行排序,这是可能的。
一种可能的解决方法是在检索后对 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
【讨论】:
以上是关于prisma 按关系排序只有 _count 属性。不能按关系字段排序的主要内容,如果未能解决你的问题,请参考以下文章
按关系属性对 NSFetchedResultsController 排序? NSFetchRequest NSSortDescriptor