У меня есть следующие модели:
User
, Customer
,Comment
Пользователь может комментировать Customer
, пользователь может отвечать на комментарии другого пользователя, рекурсивно без ограничений.
Я сделал это, но он ограничен одним ответом, и я хочу, чтобы все ответы были НЕЗАКОННЫМИ:
public async getCommentsForCustomerId(customerId: string): Promise<CustomerComment[]> {
return this.find({where: {customer: {id: customerId}, parentComment: null}, relations: ['childComments']});
}
Однако ответ, который я получаю, находится только на одном уровне:
[
{
"id": "7b5b654a-efb0-4afa-82ee-c00c38725072",
"content": "test",
"created_at": "2019-12-03T15:14:48.000Z",
"updated_at": "2019-12-03T15:14:49.000Z",
"childComments": [
{
"id": "7b5b654a-efb0-4afa-82ee-c00c38725073",
"content": "test reply",
"created_at": "2019-12-03T15:14:48.000Z",
"updated_at": "2019-12-03T15:14:49.000Z",
"parentCommentId": "7b5b654a-efb0-4afa-82ee-c00c38725072"
}
]
}
]
Как я могу сделать запрос, чтобы вложить их всех в typeorm?
Определение объекта (обратите внимание, что клиент переименован в Lead) :
@Entity('leads_comments')
export class LeadComment {
@PrimaryGeneratedColumn('uuid')
id: string;
@ManyToOne(type => LeadComment, comment => comment.childComments, {nullable: true})
parentComment: LeadComment;
@OneToMany(type => LeadComment, comment => comment.parentComment)
@JoinColumn({name: 'parentCommentId'})
childComments: LeadComment[];
@RelationId((comment: LeadComment) => comment.parentComment)
parentCommentId: string;
@ManyToOne(type => User, {cascade: true})
user: User | string;
@RelationId((comment: LeadComment) => comment.user, )
userId: string;
@ManyToOne(type => Lead, lead => lead.comments, {cascade: true})
lead: Lead | string;
@RelationId((comment: LeadComment) => comment.lead)
leadId: string;
@Column('varchar')
content: string;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
Ответы:
Вы в основном используете
Adjacency list Tree
.Список смежности - это простая модель с самообращением. Преимущество этого подхода заключается в простоте, НО недостаток в том, что вы не можете обрабатывать глубокие деревья с этим.
Есть рекурсивный способ сделать это с помощью списка смежности, но он не работает с MySQL.
Решение состоит в том, чтобы использовать другой тип дерева. Другие возможные деревья:
Для загрузки дерева используйте:
После того, как вы получите древовидный репозиторий, вы можете использовать следующие функции:
findTrees(), findRoots(), findDescendants(), findDescendantsTree()
и другие. Смотрите документацию для более.Узнайте больше о различных типах деревьев: модели для иерархических данных
источник
Как сказал Габриэль, другим моделям данных лучше делать то, что вы хотите, с точки зрения производительности. Тем не менее, если вы не можете изменить дизайн базы данных, вы можете использовать альтернативы (которые менее производительны или симпатичны, но в конечном итоге все, что работает в производстве) имеет значение.
Поскольку вы устанавливаете значение Lead в своем LeadComment, я могу предложить вам установить это значение также для ответов на корневой комментарий о создании ответов (должно быть легко в коде). Таким образом, вы можете получить все комментарии вашего клиента в одном запросе (включая ответы).
Конечно, вам нужно будет запустить пакет SQL, чтобы заполнить пропущенные значения столбцов, но это происходит один раз, и как только ваша кодовая база будет исправлена, вам не нужно будет ничего запускать впоследствии. И это не меняет структуру вашей базы данных (только способ заполнения данных).
Затем вы можете встроить в nodejs весь материал (списки ответов). Чтобы получить «корневой» комментарий, просто отфильтруйте комментарии, которые не являются ответами (у которых нет родителей). Если вам просто нужны корневые комментарии из базы данных, вы можете даже изменить запрос только на эти (с нулем parentComment в столбце SQL).
Затем вы можете получить ответы на rootComments и рекурсивно построить весь список в узле.
Вероятно, есть более оптимизированные способы вычисления этих списков, для меня это один из самых простых, которые можно сделать.
В зависимости от количества комментариев оно может стать медленным (например, вы можете ограничить результаты по отметке времени и количеству, чтобы оно было достаточно хорошим?), Так что будьте осторожны, не выбирайте вселенную комментариев по отведению "Джастин Бибер", которое получает много комментариев ...
источник