Выполнение запросов регулярных выражений с помощью pymongo

129

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

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

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

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

Тем не менее, я ничего не получаю, я что-то упускаю, потому что, согласно документам mongodb, это должно быть возможно. Если я выполняю запрос в консоли mongo, он работает нормально, означает ли это, что api не поддерживает его, или я просто использую его неправильно

RC1140
источник

Ответы:

191

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

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

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

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

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

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

RC1140
источник
9
Собственно, то, что у вас здесь есть, также сделано в javascript (и, возможно, на других языках тоже), если вы используете $regex. @ Ответ Эрика - это способ Python, который немного отличается.
drevicko
какая разница? Они оба используют python pymongo, верно? Это часть запросов mongodb, поэтому я действительно не вижу проблемы.
Декстер
10
Игнорировать регистр можно и в регулярном выражении mongodb JScript, а именно. db.collectionname.find ({'files': {'$ regex': '^ File', '$ options': 'i'}})
Аджай Гупта,
5
Этот ответ кажется мне лучше. Зачем компилировать Python RE, если вы просто собираетесь преобразовать его в строки, чтобы Mongo снова скомпилировал его? $regexОператор Монго принимает $optionsаргумент.
Марк Э. Хаасе
3
Пожалуйста, используйте r'^File'вместо, '^File'чтобы избежать других проблем
Амина Нураини
9

Чтобы избежать двойной компиляции, вы можете использовать оболочку регулярных выражений 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, поскольку есть некоторые предостережения.

Keeely
источник
1
Если вам нужно сопоставить массив с помощью $ in, тогда $ regex вам не подойдет. bson.regex.Regex сделает свое дело!
odedfos 04
4

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

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

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

Джефф
источник