skip to Main Content

I have this Mongo document

{
    _id: ObjectId('6616851ed50d6d1451fa8176'),
  phone: "+7(926)458-54-52",
  name: "Aboba"
}

I want to find that document if user inputs 7926, but also my filter is filtering another field as well.

I am filtering with regex phone or name but phone contains "+" and "()" so if user input is 7926, it wont be found.

How can I resolve that?

My regex:

{'$regex': f'\w*{request_value}\w*', '$options': 'i'}

I am filtering like that:

{$or: [name: regex, phone: regex}

2

Answers


  1. You can create a sanitized string, named phoneForSearch, with all special characters removed first. Then, use your regex search on phoneForSearch.

    db.collection.aggregate([
      {
        "$set": {
          "phoneForSearch": {
            "$reduce": {
              "input": {
                "$regexFindAll": {
                  "input": "$phone",
                  "regex": "\d+"
                }
              },
              "initialValue": "",
              "in": {
                "$concat": [
                  "$$value",
                  "$$this.match"
                ]
              }
            }
          }
        }
      },
      {
        "$match": {
          $expr: {
            $or: [
              // phone search
              {
                $ne: [
                  -1,
                  {
                    "$indexOfCP": [
                      "$phoneForSearch",
                      //user input here
                      "7926"
                    ]
                  }
                ]
              },
              // name search
              {
                "$regexMatch": {
                  "input": "$name",
                  // name regex here
                  "regex": "^abo",
                  "options": "i"
                }
              }
            ]
          }
        }
      }
    ])
    

    Mongo Playground


    You are advised to "break" the phone field into separate fields so it is easier to process and format like this:

    [
      {
        _id: ObjectId("6616851ed50d6d1451fa8176"),
        phone: {
          countryCode: "7",
          areaCode: "926",
          number: "4585452"
        },
        name: "Aboba"
      }
    ]
    

    Mongo Playground

    Login or Signup to reply.
  2. Firstly, I agree with Ray’s answer.

    create a sanitized string, named phoneForSearch

    That would allow you to also index and search better against it.

    However, if you reeeaally want to just ignore special chars, then you can do something like this:

    For phone numbers, separate each digit with D* which is "one or more non-digits". First add the D between all digits in your app/code and then search with that as a regex. So a search for 7926 against an unclean phone number could be done as:

    db.collection.find({
      phone: {
        $regex: "\D*7\D*9\D*2\D*6\D*",
        $options: "i"
      }
    })
    

    That also matches against other non-numbers like:

    +7(926)458-54-52
    +7===+++|||9....2++++6458-54-52
    +7ssss9xxxx2yyyy6dddd-458-54-52
    +7===+++|||9....2++++6458-54-52
    

    which is why it’s better to NOT do something like that.
    Mongo Playground

    And if you want to handle that D insertion in Mongo, you can do it like this:

    (updating)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search