PyMongo find() query with $or and $regex

Viewed 3692

There is a collection of MongoDB documents, containing information about books.

I need to find documents using the following criteria:

(header contains substring) OR (author contains substring)

In a mongo shell, I'm using this query and it works just fine:

db.books.find({$or: [{author: {$regex: /.*substring.*/i}}, {header: {$regex: /.*substring.*/i}}]})

BUT I can't make it work in PyMongo.

Here is my code:

search = 'substring'
search_request = {
        '$or':
            [
                {'author': {'$regex': f"/.*{search}.*/", '$options': 'i'}},
                {'header': {'$regex': f"/.*{search}.*/", '$options': 'i'}}
            ]
    } 
cursor = self.books.find(search_request)

It just returns nothing.

I'm using Python 3.7.0, PyMongo 3.7.1, MongoDB Server 3.2.11.

1 Answers

The /pattern/ syntax is Javascript literal syntax for creating regular expressions.

In Python, the same can be written without the forward slash. e.g.

search_request = {
    '$or':
        [
            {'author': {'$regex': f".*{search}.*", '$options': 'i'}},
            {'header': {'$regex': f".*{search}.*", '$options': 'i'}}
        ]
}

If you wanted to be idiomatic and create a regex object. You can do this with the same results:

import re

search = "substring"
search_expr = re.compile(f".*{search}.*", re.I)

search_request = {
    '$or': [
            {'author': {'$regex': search_expr}},
            {'header': {'$regex': search_expr}}
     ]
}
Related