Royce Schultz
Royce Schultz

Reputation: 377

PyMongo query with variables returns no results

I am trying to run a query that is constructed using a string variable, but oddly I am getting no results only when using the variable. I think this may be a bug in the pymongo package, but I want to make sure I'm not missing something.

I am running pymongo v3.11.2, mongo server v4.4, and python v3.9.

This query returns no results and exits immediately with no error:

keyword = 'some text'
results = db.myCollection.aggregate([
    {
        '$match': {
            '$text': {
                '$search': keyword  # string stored as variable
            }
        }
    }
])

While this query returns results as expected after some time computing the query:

results = db.myCollection.aggregate([
    {
        '$match': {
            '$text': {
                '$search': 'some text'  # bare string instead of variable
            }
        }
    }
])

I get similar issues within a $regexFindAll step. I do NOT have any issue when using the variable in a projection step.

I expect this would be a common use case. For example, a python backend taking user input and returning matching search results.

I have tried casting the variable as a string, encoding it, and constructing the query elsewhere all with no success.

Upvotes: 1

Views: 286

Answers (1)

Belly Buster
Belly Buster

Reputation: 8844

Not reproducible. The bash script below (requires docker) emulates your code in the exact environment documented and the values are correctly returned using a variable argument.

PROJECT_NAME=text_search

MONGODB_VERSION=4.4
PYTHON_VERSION=3.9
PYMONGO_VERSION=3.11.2

docker network create local_temp 2> /dev/null
docker run --rm --network local_temp -d --name mongodb_temp mongo:${MONGODB_VERSION}

cd "$(mktemp -d)" || exit

cat << EOF > requirements.txt
pymongo==${PYMONGO_VERSION}
EOF

cat << 'EOF' > ${PROJECT_NAME}.py
from pymongo import MongoClient, TEXT

db = MongoClient('mongodb://mongodb_temp')['mydatabase']

db.myCollection.create_index([('file_name', TEXT)])
db.myCollection.replace_one({'_id': 1}, {'_id': 1, "file_name": "Contains some text we are searching"}, upsert=True)

keyword = 'some text'

cursor = db.myCollection.aggregate([
    {'$match': {'$text': {'$search': keyword}}},
    {'$project': {'file_name': 1}}])

for item in cursor:
    print(item)
EOF

cat << EOF > Dockerfile
FROM python:${PYTHON_VERSION}
COPY ./* /
RUN pip install -r /requirements.txt
CMD ["python", "${PROJECT_NAME}.py"]
EOF

docker build --tag ${PROJECT_NAME}:latest .
docker run --rm --network local_temp --name ${PROJECT_NAME} ${PROJECT_NAME}:latest

docker stop "$(docker ps -a -q --filter name=mongodb_temp)" > /dev/null
docker image rm ${PROJECT_NAME}:latest > /dev/null
docker network rm local_temp > /dev/null

prints:

{'_id': 1, 'file_name': 'Contains some text we are searching'}

Upvotes: 3

Related Questions