2014-10-17 3 views
9

Скажем, у меня есть коллекция с этими полями:Найти матч через массив регулярных выражений в MongoDB коллекции

{ 
    "category" : "ONE", 
    "data": [ 
     { 
      "regex": "/^[0-9]{2}$/", 
      "type" : "TYPE1" 
     }, 
     { 
      "regex": "/^[a-z]{3}$/", 
      "type" : "TYPE2" 
     } 
     // etc 
    ] 
} 

Так что мой вход «а», так что я хотел бы получить соответствующий тип (или лучший матч, хотя изначально я предполагаю, что RegExes являются эксклюзивными). Есть ли какой-либо возможный способ добиться этого с достойной эффективностью? (что будет исключать итерацию по каждому элементу массива RegEx)

Обратите внимание, что схема может быть переустановлена, если это возможно, поскольку этот проект все еще находится на этапе проектирования. Поэтому можно было бы приветствовать альтернативы.

В каждой категории может быть около 100 - 150 регистров. Я планирую иметь около 300 категорий. Но я знаю, что типы взаимоисключающие.

Реальный пример мира для одной категории:

type1=^34[0-9]{4}$, 
type2=^54[0-9]{4}$, 
type3=^39[0-9]{4}$, 
type4=^1[5-9]{2}$, 
type5=^2[4-9]{2,3}$ 
+0

Как много моделей или типов вы думаете, вы будете иметь: 10, 100, 1000, Больше? –

+0

В среднем я бы сказал около 100 - 150 для каждой категории. – Dan

+0

, но вам нужно только проверить одну категорию на входную строку? –

ответ

2

Описание RegEx (Divide et Impera) значительно помогло бы ограничить количество документов, необходимых для обработки.

Некоторые идеи в этом направлении:

  • RegEx принимая длину (фиксированный, мин, макс)
  • POSIX классов стиль символов ([:alpha:], [:digit:], [:alnum:] и т.д.)
  • Дерево, подобное Структура документа (umm)

Реализация каждого из них добавит сложности (код и/или ручной ввод) для вставки, а также некоторые накладные расходы для описания searchterm перед запросом.

Наличие взаимоисключающих типов в категории упрощает вещи, но как насчет между категориями?

300 категории @ 100-150 Regexps/категория =>30к до 45K Regexps

... некоторые, несомненно, будет точные дублироваться, если не большинство из них.

В этом подходе я попытаюсь свести к минимуму общее количество документов, которые будут храниться/запрашиваться в обратном стиле по сравнению с вашей первоначальной предлагаемой «схемой».
Примечание: включены только строки длины в этой демонстрации для сужению, это может прийти естественно для ручного ввода, как это может усилить визуальный контроль над RegEx

Рассмотрим rewiting в regexes коллекции с документами следующим образом:

{ 
    "max_length": NumberLong(2), 
    "min_length": NumberLong(2), 
    "regex": "^[0-9][2]$", 
    "types": [ 
    "ONE/TYPE1", 
    "NINE/TYPE6" 
    ] 
}, 
{ 
    "max_length": NumberLong(4), 
    "min_length": NumberLong(3), 
    "regex": "^2[4-9][2,3]$", 
    "types": [ 
    "ONE/TYPE5", 
    "TWO/TYPE2", 
    "SIX/TYPE8" 
    ] 
}, 
{ 
    "max_length": NumberLong(6), 
    "min_length": NumberLong(6), 
    "regex": "^39[0-9][4]$", 
    "types": [ 
    "ONE/TYPE3", 
    "SIX/TYPE2" 
    ] 
}, 
{ 
    "max_length": NumberLong(3), 
    "min_length": NumberLong(3), 
    "regex": "^[a-z][3]$", 
    "types": [ 
    "ONE/TYPE2" 
    ] 
} 

.. каждый уникальный RegEx, как его собственный документ, имеющий категории он принадлежит (расширяемый нескольким типам в каждой категории)

Демо-код Aggregation:

function() { 

    match=null; 
    query='abc'; 

    db.regexes.aggregate(
    {$match: { 
     max_length: {$gte: query.length}, 
     min_length: {$lte: query.length}, 
     types: /^ONE\// 
     } 
    }, 
    {$project: { 
     regex: 1, 
     types: 1, 
     _id:0 
     } 
    } 
    ).result.some(function(re){ 
     if (query.match(new RegExp(re.regex))) return match=re.types; 
    }); 
    return match; 
} 

Вернуться к 'abc' запроса:

[ 
    "ONE/TYPE2" 
] 

это будет работать только против этих двух документов:

{ 
    "regex": "^2[4-9][2,3]$", 
    "types": [ 
    "ONE/TYPE5", 
    "TWO/TYPE2", 
    "SIX/TYPE8" 
    ] 
}, 
{ 
    "regex": "^[a-z][3]$", 
    "types": [ 
    "ONE/TYPE2" 
    ] 
} 

сужена по длине 3 и имеющий категорию ONE.

Может быть сужен еще больше за счет реализации POSIX дескрипторы (легко проверить против searchterm но должны ввести 2 Regexps в БД)

0

Ширина первый поиск. Если ваш ввод начинается с буквы, вы можете отбросить тип 1, если он также содержит номер, который вы можете отбросить исключительно (только цифры или только буквы), а если он также содержит символ, то сохраняйте только несколько типов, содержащих все три. Затем следуйте рекомендациям для остальных категорий. В некотором смысле, задайте случаи для типов ввода и вариантов использования для выбранного числа «типов регулярных выражений» для поиска вправо.

Или вы можете создать модель regex на основе ввода и сравнить ее с списком моделей регулярных выражений, существующих в виде строки, чтобы получить тип. Таким образом, вам просто нужно потратить ресурсы на анализ ввода, чтобы создать для него регулярное выражение.

Смежные вопросы