sql - prisma 按关系排序只有 _count 属性。不能按关系字段排序
问题描述
考虑以下 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
谢谢你!
解决方案
虽然 Prisma V2.19 引入了按关系聚合值排序,但在撰写本文时,唯一支持的聚合属性是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 是单线程的。
推荐阅读
- r - geom_dumbbell 图不继承 aes
- ionic-framework - Sending String command to BLE in Ionic
- amazon-web-services - 在 Terraform 中有条件地添加 MQ 代理用户
- ruby - Ruby class variable used like class instance variable
- c++ - C++,检测鼠标是否空闲(短时间,20ms)
- javascript - Adjust top of div after load
- c# - 将方法作为参数传递并让它订阅函数内的事件?
- python - Python:从两个列表中制作一个 csv
- java - 不存在类型变量 T 的实例,因此 ID 符合 Comparable
- string - 使用扩展函数将字符串中的每个单词大写