Can you change the order of "ORDER BY" columns created from "nested" associations in a request? #1497
-
Hey 🙂 I am trying to build a request with multiple JOINs and I need to order the results by columns coming from multiple of these JOINed tables (and in a specific order). I have an example: The database structure looks like this:
try db.create(table: "item") { table in
table.autoIncrementedPrimaryKey("id")
// ...
}
try db.create(table: "tag") { table in
table.autoIncrementedPrimaryKey("id")
table.column("importance", .integer).notNull().defaults(to: 1)
// ...
}
try db.create(table: "presentation") { table in
table.autoIncrementedPrimaryKey("id")
table.belongsTo("item", onDelete: .cascade).notNull()
table.belongsTo("relevantTag", inTable: "tag")
table.column("nextPresentationDate", .date)
// ...
} Now, I want to fetch all items and sort them based on the importance of the let observation = ValueObservation.tracking { db in
try Item
.including(
required: Item.presentation // Join the item's Presentation
.including(required: Presentation.relevantTag.order(Tag.Columns.importance.desc)) // Join the relevant tag and order by highest importance
.order(Presentation.Columns.nextPresentationDate.desc) // If importance is equal, fallback to descending presentation date to guarantee a deterministic order
)
.asRequest(of: ItemInfo.self) // Format as info object
.fetchAll(db)
} There are two ORDER BY "presentation"."nextPresentationDate" DESC, "tag"."importance" DESC What I need is to change the order of those ORDER BY columns. I want To change the order, I would need to be able to reference all the needed columns within the same One thing I played around with is using I might be missing something obvious, but I've been searching the documentation and couldn't find anything that would solve this. But maybe I'm lacking the proper search terms/keywords. I'd appreciate any help 🙂 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hello @SwiftedMind,
Your intuition is spot on. This is exactly how it should be done 👍 In the (too long) documentation for associations, the relevant section is Table Aliases. Practically speaking, you can adapt your code as below. I moved the ordering up to the outer request of items, so I needed two aliases, one for presentations and one for tags: let presentationAlias = TableAlias()
let tagAlias = TableAlias()
let presententation = Item.presentation.aliased(presentationAlias)
let tag = Presentation.relevantTag.aliased(tagAlias)
return try Item
.including(required: presententation // Join the item's Presentation
.including(required: tag) // Join the relevant tag
)
// Order by tag importance and then presentation date
// to guarantee a deterministic order
.order(
tagAlias[Tag.Columns.importance].desc,
presentationAlias[Presentation.Columns.nextPresentationDate].desc
)
// Format as info object
.asRequest(of: ItemInfo.self)
.fetchAll(db) |
Beta Was this translation helpful? Give feedback.
Hello @SwiftedMind,
Your intuition is spot on. This is exactly how it should be done 👍
In the (too long) documentation for associations, the relevant section is Table Aliases.
Practically speaking, you can adapt your code as below. I moved the ordering up to the outer request of items, so I needed two aliases, one for presentations and one for tags: