Dhinesh
Dhinesh

Reputation: 1

How to query against stored regex in mongodb

Documents are stored with regex, like

{
  "id": "id-1",
  "blocked": [
    "abcd.com/[a-z]+",
    "efgh.com/[0-9]+"
  ]
},
{
  "id": "id-2",
  "blocked": [
    "pqrs.com/[\w]+",
    "xyz.com/[.]+"
  ]
}

Basically I am looking how to query against the stored regex.

Case 1: If I pass "abcd.com/mongodb" then it mataches with the first document. So query should retrun first document

Case 2: If I pass "google.com/mongo" then it does not match with any stored regex. So query should return empty array.

Upvotes: 0

Views: 450

Answers (2)

Mallik
Mallik

Reputation: 334

//MongoDB version on windows(actual code output from mongo shell 4.2 on windows)
> db.version();
4.2.6
//prepare the same data and query it as below, per problem statement
> db.test5.find()
{ "_id" : ObjectId("5f721b8a3d04e9033d482a9b"), "id" : "id-1", "blocked" : [ "abcd.com/[a-z]+", "efgh.com/[0-9]+" ] }
{ "_id" : ObjectId("5f721b8a3d04e9033d482a9c"), "id" : "id-2", "blocked" : [ "pqrs.com/[w]+", "xyz.com/[.]+" ] }
declare variables to include the string for which regex can be checked from collection
> var1 = "abcd.com/mongodb";
abcd.com/mongodb
> var2 = "google.com/mongo";
google.com/mongo
//actual code output from mongo shell using aggregate
//you need to use $regexMatch to match the variable string to that is stored in the collection
> db.test5.aggregate([
... {$unwind:"$blocked"},
... {$addFields:{result1:{$regexMatch:{input:var1,regex:"$blocked"}}}},
... {$addFields:{result2:{$regexMatch:{input:var2,regex:"$blocked"}}}}
... ]);
{ "_id" : ObjectId("5f721b8a3d04e9033d482a9b"), "id" : "id-1", "blocked" : "abcd.com/[a-z]+", "result1" : true, "result2" : false }
{ "_id" : ObjectId("5f721b8a3d04e9033d482a9b"), "id" : "id-1", "blocked" : "efgh.com/[0-9]+", "result1" : false, "result2" : false }
{ "_id" : ObjectId("5f721b8a3d04e9033d482a9c"), "id" : "id-2", "blocked" : "pqrs.com/[w]+", "result1" : false, "result2" : false }
{ "_id" : ObjectId("5f721b8a3d04e9033d482a9c"), "id" : "id-2", "blocked" : "xyz.com/[.]+", "result1" : false, "result2" : false }
>
//the result will be true or false boolean.
//Hope, you can use this result to process your further logic of return array or empty string
//eg. case1 per your requirements: Since var1 matches with string it matches to true
//similarly case2 per your requirements: Since var2 does not match it returns false

Upvotes: 1

sjahan
sjahan

Reputation: 5950

Not sure I totally get your problem, but here is a quick attempt to solve what I think I got!

Feel free to comment. It is not optimized: creating new RegExp every iteration is probably not the best idea, just simpler to implement!

const documents = [{
  "id": "id-1",
  "blocked": [
    "abcd.com/[a-z]+",
    "efgh.com/[0-9]+"
  ]
},
{
  "id": "id-2",
  "blocked": [
    "pqrs.com/[\w]+",
    "xyz.com/[.]+"
  ]
}];

const inputs = ["abcd.com/mongodb", "google.com/mongo"];

function check(input) {
  documents.forEach(document => {
    const matchFound = document.blocked.some(regexp => new RegExp(regexp).test(input));
    if(matchFound) {
      console.log(`Input '${input} matched document ${document.id}'`);
    }
  });
}

inputs.forEach(check);

Upvotes: 0

Related Questions