NestJS नोडज ने संबंधों के साथ एक प्रश्न में नेस्टेड टिप्पणी लोड की है?


10

मेरे पास निम्न मॉडल हैं:

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"
            }
        ]
    }
]

मैं उन सभी प्रकार के घोंसले में घोंसला बनाने के लिए एक प्रश्न कैसे बना सकता हूं?

इकाई की परिभाषा (नोट ग्राहक का नाम बदलकर लीड) :

@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;
}

1
क्या आप अपनी इकाई की परिभाषा जोड़ सकते हैं?
ज़ेनबेनी

@zenbeni जोड़ा गया धन्यवाद
बेन बेरी

जवाबों:


7

आप मूल रूप से एक का उपयोग कर रहे हैं Adjacency list Tree

आत्म-संदर्भित के साथ आसन्न सूची एक सरल मॉडल है। इस दृष्टिकोण का लाभ सादगी है, लेकिन दोष यह है कि आप इसके साथ गहरे पेड़ों को संभाल नहीं सकते हैं।

आसन्न सूची के साथ इसे करने का एक पुनरावर्ती तरीका है, लेकिन यह MySQL के साथ काम नहीं करता है।

समाधान एक अन्य प्रकार के पेड़ का उपयोग करना है। अन्य संभावित पेड़ हैं:

  • नेस्टेड सेट : यह बहुत ही कुशल है, लेकिन लिखने के लिए बुरा है। नेस्टेड सेट में आपकी कई जड़ें नहीं हो सकती हैं।
  • भौतिकवादी पथ : (जिसे पथ गणना भी कहा जाता है) सरल और प्रभावी है।
  • समापन तालिका : माता-पिता और बच्चे के बीच एक अलग तालिका में संबंधों को संग्रहीत करता है। दोनों को पढ़ने और लिखने में कुशल है (घटक के माता-पिता को अपडेट करना या हटाना अभी तक लागू नहीं किया गया है)
@Entity()
@Tree("nested-set") // or @Tree("materialized-path") or @Tree("closure-table")
export class Category {

    @PrimaryGeneratedColumn()
    id: number;

    @TreeChildren()
    children: Category[];

    @TreeParent()
    parent: Category;
}

एक पेड़ के उपयोग को लोड करने के लिए:

const manager = getManager();
const trees = await manager.getTreeRepository(Category).findTrees();

एक पेड़ के भंडार को प्राप्त करने के बाद, आप अगले कार्यों का उपयोग कर सकते हैं: findTrees(), findRoots(), findDescendants(), findDescendantsTree()और अन्य। अधिक के लिए प्रलेखन देखें ।

विभिन्न प्रकार के पेड़ों के बारे में अधिक जानें: पदानुक्रमित डेटा के लिए मॉडल


1

जैसा कि गेब्रियल ने कहा, अन्य डेटा मॉडल बेहतर हैं जो आप प्रदर्शन के लिए चाहते हैं। फिर भी यदि आप डेटाबेस डिज़ाइन को नहीं बदल सकते हैं, तो आप विकल्प का उपयोग कर सकते हैं (जो कम प्रदर्शन करने वाले या सुंदर हैं, लेकिन उत्पादन में जो काम करता है वह अंत में मायने रखता है)।

जैसा कि आप अपने लीडकॉम में लीड मान सेट करते हैं, मैं सुझाव दे सकता हूं कि आप इस मूल्य को उत्तर निर्माण पर मूल टिप्पणी पर उत्तर में भी सेट करें (कोड में आसान होना चाहिए)। इस तरह से आप अपने ग्राहक पर सभी टिप्पणियों को एक प्रश्न (उत्तरों सहित) में ला सकते हैं।

const lead = await leadRepository.findOne(id);
const comments = await commentRepository.find({lead});

बेशक, आपको अनुपलब्ध स्तंभ मानों को पॉप्युलेट करने के लिए SQL बैच चलाना होगा, लेकिन यह एक बार की बात है, और एक बार जब आपका कोडबेस पैच हो जाता है तो आपको बाद में कुछ भी चलाने की आवश्यकता नहीं होगी। और यह आपके डेटाबेस की संरचना को नहीं बदलता (जिस तरह से डेटा आबादी है)।

फिर आप पूरी सामग्री (उत्तरों की सूची) नोडज में बना सकते हैं। "रूट" टिप्पणी पाने के लिए, केवल टिप्पणी द्वारा फ़िल्टर करें जो उत्तर नहीं हैं (जिसमें माता-पिता नहीं हैं)। यदि आप केवल डेटाबेस से मूल टिप्पणियां चाहते हैं, तो आप क्वेरी को केवल इन (SQL कॉलम में पैरेंटकॉममेंट नल के साथ) बदल सकते हैं।

function sortComment(c1: LeadComment , c2: LeadComment ): number {
    if (c1.created_at.getTime() > c2.created_at.getTime()) {
    return 1;
    }
    if (c1.created_at.getTime() < c2.created_at.getTime()) {
        return -1;
    }
    return 0;
}
const rootComments = comments
    .filter(c => !c.parentComment)
    .sort(sortComment);

तब आप rootComments पर उत्तर प्राप्त कर सकते हैं और पूरी सूची को पुन: नोड में बना सकते हैं।

function buildCommentList(currentList: LeadComment[], allComments: LeadComment[]): LeadComment[] {
    const lastComment = currentList[currentList.length - 1];
    const childComments = allComments
        .filter(c => c.parentComment?.id === lastComment.id)
        .sort(sortComment);
    if (childComments.length === 0) {
        return currentList;
    }
    const childLists = childComments.flatMap(c => buildCommentList([c], allComments));
    return [...currentList, ...childLists];
}

const listsOfComments = rootComments.map(r => buildCommentList([r], comments));

इन सूचियों की गणना करने के लिए शायद अधिक अनुकूलित तरीके हैं, यह मेरे लिए सबसे सरल में से एक है जो बनाया जा सकता है।

टिप्पणियों की संख्या के आधार पर यह धीमा हो सकता है (उदाहरण के लिए टाइमस्टैम्प और संख्या द्वारा आप परिणाम सीमित कर सकते हैं ताकि यह काफी अच्छा हो?) इसलिए सावधान रहें, "जस्टिन बीबर" लीड पर टिप्पणियों का ब्रह्मांड प्राप्त न करें कई टिप्पणियाँ ...

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.