Лучший способ реализовать отношение [пользователь - подписки / подписчики] в базе данных
Я пишу сервер, используя Swift 4 + Vapor Framework, Fluent ORM и PostgreSQL в качестве драйвера. У меня есть пользовательская модель, которая должна иметь подписчиков и подписки (которые также являются пользовательскими моделями). У меня есть два варианта: 1. хранить массивы с уникальными идентификаторами подписок / подписчиков или 2. строить отношение "один-ко-многим" между пользователем и пользователем. Как вы думаете, какой из них лучше, и как я могу это реализовать?
1 ответ
Хранение массива не является оптимальным. Запрос к вашей базе данных, чтобы найти всех подписчиков пользователя, потребует анализа каждого массива подписок пользователя и поиска тех, которые содержат идентификатор вашего целевого пользователя. Отношение это лучшая идея.
Свободно использует класс Pivot для моделирования отношений "многие ко многим". Поскольку это отношение со ссылками на себя, во избежание конфликтов ключей идентификаторов вам, вероятно, будет проще создать свою собственную сквозную модель.
import FluentProvider
import Vapor
final class Subscription: Model, PivotProtocol {
typealias Left = User
typealias Right = User
var subscriberId: Identifier
var subscribedId: Identifier
init(
subscriberId: Identifier,
subscribedId: Identifier
) {
self.subscriberId = subscriberId
self.subscribedId = subscribedId
}
let storage = Storage()
static let leftIdKey = "subscriber_id"
static let rightIdKey = "subscribed_id"
init(row: Row) throws {
subscriberId = try row.get("subscriber_id")
subscribedId = try row.get("subscribed_id")
}
func makeRow() throws -> Row {
var row = Row()
try row.set("subscriber_id", subscriberId)
try row.set("subscribed_id", subscribedId)
return row
}
}
extension User {
var subscribers: Siblings<User, User, Subscription> {
return siblings(localIdKey: "subscriber_id", foreignIdKey: "subscribed_id")
}
var subscribed: Siblings<User, User, Subscription> {
return siblings(localIdKey: "subscribed_id", foreignIdKey: "subscriber_id")
}
}