0

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.

MauriceNino
  • 6,214
  • 1
  • 23
  • 60
  • Does this answer your question? [Converting user input string to regular expression](https://stackoverflow.com/questions/874709/converting-user-input-string-to-regular-expression) – sjahan Sep 28 '20 at 13:59
  • it might not work, If i convert my input to regex, `\abcd.com\mongodb\$` then it will not match with text `abcd.com/[a-z]+` – Dhinesh Sep 28 '20 at 14:04
  • You mean the other way? `abcd.com/[a-z]+` won't match `\abcd.com\mongodb\$`? Well maybe your regexp is wrong... I don't really understand your problem here. If you want to convert a string to a regex, use the constructor `new RegExp()` and it does the job. Right? – sjahan Sep 28 '20 at 14:17
  • 1
    @sjahan Thanks for supporting. Usually we store `text` in the document and query using `$regex` which will be supplied. But this scenario is bit different. Here we stored `some regex`, and I have `text` which will be supplied. Now I want to return the documents which satisfy the matches. It is like reverse regex. – Dhinesh Sep 28 '20 at 14:24

2 Answers2

1
//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
Mallik
  • 336
  • 2
  • 6
0

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);
sjahan
  • 5,720
  • 3
  • 19
  • 42