Eu tenho os seguintes modelos:
User
, Customer
,Comment
O usuário pode comentar em um Customer
, o usuário pode responder ao comentário de outro usuário, recursivamente ilimitado.
Fiz isso, mas é limitado a apenas uma resposta e desejo obter todas as respostas NESTED:
public async getCommentsForCustomerId(customerId: string): Promise<CustomerComment[]> {
return this.find({where: {customer: {id: customerId}, parentComment: null}, relations: ['childComments']});
}
No entanto, a resposta que recebo é aninhada apenas em um nível:
[
{
"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"
}
]
}
]
Como posso fazer uma consulta para aninhar todos eles em typeorm?
Definição da entidade (observe o cliente renomeado para 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;
}
Respostas:
Você está basicamente usando um
Adjacency list Tree
.A lista de adjacências é um modelo simples com auto-referência. O benefício dessa abordagem é a simplicidade, MAS a desvantagem é que você não pode lidar com árvores profundas com isso.
Existe uma maneira recursiva de fazê-lo com a lista Adjacency, mas não funciona com o MySQL.
A solução é usar outro tipo de árvore. Outras árvores possíveis são:
Para carregar uma árvore, use:
Depois de obter um repositório em árvore, você pode usar as próximas funções:
findTrees(), findRoots(), findDescendants(), findDescendantsTree()
e outras. Consulte a documentação para obter mais informações.Saiba mais sobre diferentes tipos de árvores: Modelos para dados hierárquicos
fonte
Como Gabriel disse, outros modelos de dados são melhores para fazer o que você deseja em termos de desempenho. Ainda assim, se você não pode alterar o design do banco de dados, pode usar alternativas (que têm menos desempenho ou são bonitas, mas o que funciona na produção é tudo o que importa no final).
Conforme você define o valor Lead em seu LeadComment, posso sugerir que você defina esse valor também nas respostas no comentário raiz sobre a criação de respostas (deve ser fácil no código). Dessa forma, você pode buscar todos os comentários sobre seu cliente em uma consulta (incluindo as respostas).
Obviamente, você precisará executar um lote SQL para preencher os valores de coluna ausentes, mas isso é uma coisa única e, uma vez que sua base de código também esteja corrigida, você não precisará executar nada depois. E isso não altera a estrutura do seu banco de dados (apenas a maneira como os dados são preenchidos).
Em seguida, você pode criar no nodejs todo o material (listas de respostas). Para obter o comentário "raiz", basta filtrar por comentário que não seja uma resposta (que não tenha pais). Se você deseja apenas os comentários raiz do banco de dados, você pode alterar a consulta apenas para esses (com parentComment nulo na coluna SQL).
Em seguida, você pode obter respostas nos rootComments e criar a lista inteira recursivamente no nó.
Provavelmente existem maneiras mais otimizadas de calcular essas listas; essa é para mim uma das mais simples que podem ser feitas.
Dependendo do número de comentários, ele pode ficar lento (você pode limitar os resultados com carimbo de data e hora e número, por exemplo, para que seja bom o suficiente?). Cuidado, não procure o universo de comentários em um lead "Justin Bieber" que recebe muitos comentários ...
fonte