Search code examples
mongodbmongoosemongodb-queryaggregation-frameworkmongoose-populate

Mongoose- Search/Filter data from array into another array with the specific items


I have an mongoDB object like

{   
    "courseName" : "AI",
    "user" : ObjectId("6087dc4c2ba7a828363c9fca"),
    "questions" : [ 
        { 
             "optionsSet" : [ 
                {
                    "value" : "A",
                },
                {
                    "value" : "B",
                }
             ],
            "topics" : ["b", "c", "a"],
            "createdAt" : "2021-07-07T18:41:18.971Z"
        }, 
        {
           "optionsSet" : [ 
                {
                    "value" : "C",
                },
                {
                    "value" : "D",
                }
             ],
            "topics" : ["c"],
            "createdAt" : "2021-08-07T18:41:18.971Z
        },
        {
            "optionsSet" : [ 
                {
                    "value" : "CC",
                },
                {
                    "value" : "DD",
                }
             ],
            "topics" : ["b"],
            "createdAt" : "2021-08-07T18:41:30.971Z"
        }
    ]
}

Sometime I have to use only match the courseName and user only.

Another time I have to query with the courseName user and topics where topics which at least match one topic. How can i handle this process?

When I pass input as courseName, user and topics ["b"]. I deselected user and optionsSet in return output. My expected out put will be :

{
    "courseName" : "AI",
    "questions" : [ 
        {
            "topics" : ["b", "c", "a"],
        }, 
        {
            "topics" : ["b"],
        }
    ]
}

Is this possible?


Solution

  • You can use aggregation query,

    • $match to check your condition using $in operator
    • $filter to iterate loop of questions and check if topics having any input search topics
    • $filter to iterate loop of topics and search for topics
    let p = YourSchema.aggregate();
    
    // courseName
    if (req.body.courseName) p.match({ courseName: req.body.courseName });
    
    // user
    if (req.body.user) p.match({ user: req.body.user });
    
    // topics
    if (req.body.topics) {
      p.match({ "questions.topics": { $in: req.body.topics } });
    
      p.addFields({
        questions: {
          $filter: {
            input: "$questions",
            cond: {
              $ne: [
                {
                  $filter: {
                    input: "$$this.topics",
                    cond: { $in: ["$$this", req.body.topics] }
                  }
                },
                []
              ]
            }
          }
        }
      });
    }
    
    let result = await p.exec();
    

    Playground