Mam następujące modele:
User
, Customer
,Comment
Użytkownik może komentować Customer
, użytkownik może odpowiadać na komentarze innego użytkownika, rekurencyjnie nieograniczony.
Zrobiłem to, ale ogranicza się to tylko do jednej odpowiedzi i chcę otrzymać wszystkie odpowiedzi NESTED:
public async getCommentsForCustomerId(customerId: string): Promise<CustomerComment[]> {
return this.find({where: {customer: {id: customerId}, parentComment: null}, relations: ['childComments']});
}
Jednak odpowiedź, którą otrzymuję, jest zagnieżdżona tylko na jednym poziomie:
[
{
"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"
}
]
}
]
Jak mogę utworzyć zapytanie, aby zagnieździć je wszystkie wormorm?
Definicja jednostki (uwaga klienta zmieniono nazwę na 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;
}
Odpowiedzi:
Zasadniczo używasz
Adjacency list Tree
.Lista adiacyencji jest prostym modelem z samodzielnymi odniesieniami. Zaletą tego podejścia jest prostota, ALE wadą jest to, że nie radzisz sobie z głębokimi drzewami.
Jest rekurencyjny sposób na zrobienie tego z listą Adjacency, ale nie działa z MySQL.
Rozwiązaniem jest użycie innego rodzaju drzewa. Inne możliwe drzewa to:
Aby załadować drzewo, użyj:
Po otrzymaniu repozytorium drzewa możesz użyć kolejnych funkcji:
findTrees(), findRoots(), findDescendants(), findDescendantsTree()
i innych. Więcej informacji znajduje się w dokumentacji .Dowiedz się więcej o różnych typach drzew: Modele danych hierarchicznych
źródło
Jak powiedział Gabriel, inne modele danych lepiej robić to, co chcesz pod względem wydajności. Mimo to, jeśli nie możesz zmienić projektu bazy danych, możesz użyć alternatyw (które są mniej wydajne lub ładne, ale to, co działa w produkcji, jest w końcu najważniejsze).
Gdy ustawiasz wartość Lead w swoim LeadComment, mogę zasugerować, abyś ustawił tę wartość również w odpowiedziach na komentarz roota podczas tworzenia odpowiedzi (powinno to być łatwe w kodzie). W ten sposób możesz pobrać wszystkie komentarze dotyczące klienta w jednym zapytaniu (łącznie z odpowiedziami).
Oczywiście będziesz musiał uruchomić pakiet SQL, aby uzupełnić brakujące wartości kolumn, ale jest to jednorazowa sprawa, a gdy baza kodów zostanie załatana, nie będziesz musiał później nic uruchamiać. I to nie zmienia struktury bazy danych (tylko sposób zapełniania danych).
Następnie możesz wbudować w nodejs całe rzeczy (listy odpowiedzi). Aby uzyskać komentarz „root”, po prostu filtruj według komentarzy, które nie są odpowiedziami (które nie mają rodziców). Jeśli chcesz tylko główne komentarze z bazy danych, możesz nawet zmienić zapytanie tylko na te (z parentComment null w kolumnie SQL).
Następnie możesz uzyskać odpowiedzi na rootComments i zbudować rekurencyjnie całą listę w węźle.
Prawdopodobnie istnieją bardziej zoptymalizowane sposoby obliczania tych list, jest to dla mnie jeden z najprostszych, jakie można wykonać.
W zależności od liczby komentarzy może się spowolnić (możesz na przykład ograniczyć wyniki według znacznika czasu i liczby, aby było wystarczająco dobre?), Więc uważaj, nie ściągaj uniwersum komentarzy na temat potencjalnej szansy „Justin Bieber” wiele komentarzy ...
źródło