J'ai les modèles suivants:
User
, Customer
,Comment
L'utilisateur peut commenter un Customer
, l'utilisateur peut répondre au commentaire d'un autre utilisateur, récursivement illimité.
Je l'ai fait mais c'est limité à une seule réponse, et je veux obtenir toutes les réponses IMPRIMÉ:
public async getCommentsForCustomerId(customerId: string): Promise<CustomerComment[]> {
return this.find({where: {customer: {id: customerId}, parentComment: null}, relations: ['childComments']});
}
Cependant, la réponse que j'obtiens n'est imbriquée qu'à un seul niveau:
[
{
"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"
}
]
}
]
Comment puis-je faire une requête pour les imbriquer tous dans typeorm?
Définition d'entité (notez que le client a été renommé 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;
}
Réponses:
Vous utilisez essentiellement un
Adjacency list Tree
.La liste d'adjacence est un modèle simple avec auto-référencement. L'avantage de cette approche est la simplicité, MAIS l'inconvénient est que vous ne pouvez pas gérer les arbres profonds avec cela.
Il existe une manière récursive de le faire avec la liste d'adjacence, mais cela ne fonctionne pas avec MySQL.
La solution consiste à utiliser un autre type d'arbre. D'autres arbres possibles sont:
Pour charger un arbre, utilisez:
Après avoir obtenu un référentiel arborescent, vous pouvez utiliser les fonctions suivantes:
findTrees(), findRoots(), findDescendants(), findDescendantsTree()
et d'autres. Consultez la documentation pour en savoir plus.En savoir plus sur les différents types d'arbres: modèles de données hiérarchiques
la source
Comme Gabriel l'a dit, les autres modèles de données font mieux ce que vous voulez en termes de performances. Néanmoins, si vous ne pouvez pas modifier la conception de la base de données, vous pouvez utiliser des alternatives (qui sont moins performantes ou jolies, mais ce qui fonctionne en production est tout ce qui compte au final).
Lorsque vous définissez la valeur Lead dans votre LeadComment, je peux vous suggérer de définir cette valeur également sur les réponses sur le commentaire racine sur la création de la réponse (cela devrait être facile dans le code). De cette façon, vous pouvez récupérer tous les commentaires sur votre client en une seule requête (y compris les réponses).
Bien sûr, vous devrez exécuter un lot SQL pour remplir les valeurs de colonne manquantes, mais c'est une chose unique, et une fois votre base de code corrigée, vous n'aurez plus rien à exécuter par la suite. Et cela ne change pas la structure de votre base de données (juste la façon dont les données sont remplies).
Ensuite, vous pouvez construire dans nodejs le tout (listes de réponses). Pour obtenir le commentaire "racine", filtrez simplement par commentaire qui ne sont pas des réponses (qui n'ont pas de parents). Si vous voulez simplement les commentaires racine de la base de données, vous pouvez même modifier la requête uniquement à ceux-ci (avec parentComment null dans la colonne SQL).
Ensuite, vous pouvez obtenir des réponses sur rootComments et créer la liste entière de manière récursive dans le nœud.
Il existe probablement des moyens plus optimisés pour calculer ces listes, c'est pour moi l'une des plus simples qui puisse être faite.
En fonction du nombre de commentaires, cela peut devenir lent (vous pouvez limiter les résultats par horodatage et nombre par exemple pour qu'il soit suffisant?) Alors attention, ne récupérez pas l'univers des commentaires sur un Lead "Justin Bieber" beaucoup de commentaires ...
la source