Выполнение запросов регулярных выражений с PyMongo

Я пытаюсь выполнить запрос регулярного выражения с помощью PyMongo на сервере MongoDB. Структура документа следующая

{
  "files": [
    "File 1",
    "File 2",
    "File 3",
    "File 4"
  ],
  "rootFolder": "/Location/Of/Files"
}

Я хочу получить все файлы, соответствующие шаблону * File. Я пробовал делать это как таковой

db.collectionName.find({'files':'/^File/'})

Но я ничего не получаю обратно. Я что-то упускаю, потому что, согласно документам MongoDB, это должно быть возможно? Если я выполняю запрос в консоли Mongo, он работает нормально, означает ли это, что API не поддерживает его, или я просто использую его неправильно?


person RC1140    schedule 14.08.2010    source источник


Ответы (4)


Если вы хотите включить параметры регулярного выражения (например, игнорировать регистр), попробуйте следующее:

import re
regx = re.compile("^foo", re.IGNORECASE)
db.users.find_one({"files": regx})
person Eric    schedule 02.02.2011
comment
Также обратите внимание, что регулярные выражения, привязанные в начале (т.е. начиная с ^), могут использовать индексы в базе данных и в этом случае будут работать намного быстрее. - person drevicko; 14.08.2013
comment
Регулярные выражения, начинающиеся с ^, могут использовать индекс только в определенных случаях. При использовании re.IGNORECASE я считаю, что mongo не может использовать индекс для выполнения запроса. - person nonagon; 08.04.2015
comment
Это использование где-то задокументировано? Я не могу найти это в официальном документе API pymongo. - person Hieu; 17.10.2017

Оказывается, поиск по регулярным выражениям в pymongo выполняется немного по-другому, но так же просто.

Регулярное выражение выполняется следующим образом:

db.collectionname.find({'files':{'$regex':'^File'}})

Это будет соответствовать всем документам, у которых есть свойство files, в котором есть элемент, начинающийся с File

person RC1140    schedule 14.08.2010
comment
На самом деле то, что у вас здесь, также является способом, которым это делается в javascript ( и, возможно, другие языки тоже), если вы используете $regex. @ Ответ Эрика - это способ Python, который немного отличается. - person drevicko; 14.08.2013
comment
какая разница? Они оба используют python pymongo, верно? Это часть запросов mongodb, поэтому я действительно не вижу проблемы. - person Dexter; 22.12.2014
comment
Игнорировать регистр можно и в регулярном выражении mongodb JScript, а именно. db.collectionname.find ({'files': {'$ regex': '^ File', '$ options': 'i'}})) - person Ajay Gupta; 25.04.2015
comment
Этот ответ кажется мне лучше. Зачем компилировать Python RE, если вы собираетесь просто преобразовать его в строки, чтобы Mongo снова скомпилировал его? Оператор Mongo $regex принимает аргумент $options. - person Mark E. Haase; 16.05.2015
comment
Пожалуйста, используйте r'^File' вместо '^File', чтобы избежать других проблем - person Aminah Nuraini; 02.12.2015
comment
Спасибо за этот ответ. Я попытался сделать то, что, как я думал, будет простым расширением этого, чтобы вернуть все файлы, начинающиеся с букв A-F, как показано ниже. - person Richard B; 17.08.2016
comment
Также стоит отметить, что все еще можно использовать переменные в регулярном выражении при такой компиляции: db.collectionname.find({'files':{'$regex':'^{}'.format(myVar)}}) - person Andrew Kirk; 09.06.2017
comment
кто-нибудь ответит на мой вопрос stackoverflow.com/questions/49843914/ - person pyd; 15.04.2018

Чтобы избежать двойной компиляции, вы можете использовать оболочку регулярных выражений bson, которая поставляется с PyMongo:

>>> regx = bson.regex.Regex('^foo')
>>> db.users.find_one({"files": regx})

Regex просто сохраняет строку, не пытаясь ее скомпилировать, поэтому find_one может затем определить аргумент как тип Regex и сформировать соответствующий запрос Mongo.

Я чувствую, что этот способ немного более питонический, чем другой главный ответ, например:

>>> db.collectionname.find({'files':{'$regex':'^File'}})

Если вы планируете использовать запросы с регулярными выражениями, стоит прочитать документацию по bson Regex, поскольку есть некоторые предостережения.

person Keeely    schedule 23.05.2018
comment
Если вам нужно сопоставить массив с помощью $ in, тогда $ regex вам не подойдет. bson.regex.Regex сделает свое дело! - person odedfos; 04.07.2018

Решение re вообще не использует индекс. Вам следует использовать такие команды, как:

db.collectionname.find({'files':{'$regex':'^File'}})

(Я не могу комментировать их ответы, поэтому отвечаю здесь)

person Jeff    schedule 16.08.2018