Запрос pymongo с нечувствительным к регистру текстом

Ниже показано, как я запрашиваю данные из моего mongodb с помощью pymongo:

def is_philippine_facebook(self,facebook_user):
        is_philippine = False
        db_server = self.ConfigSectionMap('db_server')
        database_name = db_server['database']
        db = self.client[database_name]
        cursor = db[collection_name].find({
                'isPhilippine':True,
                'facebook_user': re.compile('@'+facebook_user, re.IGNORECASE)
            })
        for document in cursor:
            if document is not None:
                is_philippine = True
                break
        return is_philippine

На самом деле, я хочу запросить записи, имеющие определенный facebook_user с нечувствительным вариантом. Тем не менее, запрос возвращает много неверных результатов. Например, если facebook_user является WWF, записи с WWF_XYZ будет возвращен.

Как я могу это исправить? Благодарю.

2 ответа

Решение

Похоже, вы хотите слово границы \b

'facebook_user': re.compile('@'+ facebook_user +'\\b', re.IGNORECASE)

Так что если вы поставите WWF или же wwf тогда оно совпадает только до конца "слова", а не за его пределами.

Как примечание, регистр не учитывает поиск, не связанный с кареткой ^ Для начала строки требуют полного сканирования коллекции и не очень эффективны.

Если вы соответствуете началу строки, вы должны использовать символ вставки, и вам, вероятно, следует нормализовать регистр в качестве свойства документа для поиска, чтобы вам также не требовалась опция "без учета регистра". Эти две вещи необходимы для индекса, который будет использоваться при поиске. Увидеть $regex в документации

Используйте следующее исправление:

re.compile(r'@{0}\b'.format(facebook_user), re.IGNORECASE)

Смотрите демо-версию регулярного выражения.

Детали шаблона:

  • @WWF - буквальный @WWF
  • \b - граница слова (требуется символ, отличный от буквы, цифры или _или конец строки после @WWF)

Если facebook_user может содержать специальные символы, вам нужно использовать

re.compile(r'(?<!\w)@{0}(?!\w)'.format(re.escape(facebook_user)), re.IGNORECASE)

Тем не менее facebook_user кажется, содержит только символы слова, так что в этом случае действительно должно быть достаточно границы слова.

Другие вопросы по тегам