Malik Awan
Malik Awan

Reputation: 463

How to build Dynamic MongoDB Query

I have 2 collections MongoDB. Keyword and PersonalInfo. I am receiving an array from client side like this:

[
 {fieldName : 'Keyword',operator: '===',value: 'soccer'},
 {fieldName : 'Keyword',operator: 'endsWith',value: 'cer'},
 {fieldName : 'Name',operator: 'startsWith',value: 'mik'}
]

I am using NodeJs where i need to build MongoDB query dynamically. I have tried like this.

 let q = {};
  q["$and"] = [];

  let data = req.body;
  for (let i = 0; i < data.length; i++) {
    // I tried without consideration of "operator" first but couldn't succeed. 

    let val = new RegExp(data[i].value);
    if (data[i].fieldName === "Keyword") {
      q["$and"].push({ Keyword: { $regex: val, $options: "-i" } });
    } else if (data[i].fieldName === "Name") {
      q["$and"].push({ Name: { $regex: val, $options: "-i" } }); //Since this field is from another collection, so instead of Name i want to push it as "$$name" so i could be able to use it in aggregates. 


    } 
  }

I was expecting to see an output like this.

{$and: 
[
 {Keyword: {$regex: 'search val', $options: "-i"}},
 {Name: {$regex: 'search val', $options: "-i"}},
]
}

But what i got is:

{$and: 
 [
 {Keyword: [Object]},
 {Name: [Object]},
]
}

How can i build the above query and implement this in aggregate like;

await Keyword.aggregate([
 {
  $lookup: {
    from: "PersonalInfo",
    let: { name: "$Name" },
    pipeline: [{ $match: { $expr: q } }],
    as: "searchRecords"
  }
}
 ])

Here is my full code altogether.

let q = {};
  let results;
  let data = req.body;
  let and_conds = [];
  for (let i = 0; i < data.length; i++) {
    let val = new RegExp(data[i].value);
    let field_name = data[i].fieldName;
    and_conds.push({ [field_name]: { $regex: val, $options: "-i" } });
  }
  q["$and"] = and_conds;

let records = await KeyInfo.aggregate([
   {
      $lookup: {
        from: "PersonalInfo",
        let: { name: "$name" },
        pipeline: [{ $match: { $expr: q } }],
        as: "searchRecords"
      }
    }
   ]);

Thanks for your time and appreciate your help.

Upvotes: 0

Views: 1128

Answers (1)

Tom Slabbaert
Tom Slabbaert

Reputation: 22276

You're doing it correctly, i'm not sure how you got your "output" (assuming you printed it) but its just showing you whats inside your object which is another object as expected.

The full code would look like this: (cleared it a little for read-ability only)

  let q = {};

  let data = req.body;
  let and_conds = [];
  for (let i = 0; i < data.length; i++) {
    let val = new RegExp(data[i].value);
    let field_name = data[i].fieldName;
    and_conds.push({[field_name]: { $regex: val, $options: "-i" }})
  } 
  q["$and"] = and_conds;
  • i'm not sure what you meant with the $$name comment as your only using these conditions after the lookup in the match phase but if all you have to do is change the field_name value from "Name" to "$$name".

EDIT:

use this instead of the syntax above:

    let val = new RegExp(data[i].value, "i");
    and_conds.push({[field_name]: val)`

also you didnt change ur fieldName to be "$$name" you should do that too.

Upvotes: 1

Related Questions