Operador de Agregação do MongoDB: $regexMatch

O operador $regexMatch executa uma correspondência de padrão de expressão regular (regex) e retorna:

  • true se houver correspondência
  • false se não houver correspondência

Antes do MongoDB 4.2, o pipeline de agregação só podia usar o operador de consulta $regex no estágio $match.

Sintaxe

{ $regexMatch: { input: <expression> , regex: <expression>, options: <expression> } }

O $regexMatch pode ser usado para comparar qualquer tipo de valor, utilizando a ordem de comparação BSON específica para cada tipo.

Campos

  • input: A string na qual o padrão de expressão regular será aplicado. Pode ser uma string ou qualquer expressão que resulte em uma string.

  • regex: O padrão de expressão regular a ser aplicado. Pode ser qualquer expressão que resulte em uma string ou em um padrão regex /<pattern>/. Ao usar /<pattern>/, você também pode especificar as opções i e m (mas não s ou x):

    • "pattern"
    • /<pattern>/
    • /<pattern>/<options>

    Alternativamente, você pode usar o campo options para especificar as opções. Para usar as opções s ou x, é obrigatório usar o campo options.

    Não é permitido especificar opções simultaneamente nos campos regex e options.

  • options: Campo opcional. As seguintes <options> podem ser usadas com a expressão regular:

    • i: Ignora diferenças entre maiúsculas e minúsculas. Pode ser especificado no campo options ou como parte do campo regex.
    • m: Para padrões que contêm âncoras (como ^ para início e $ para fim), corresponde ao início ou ao fim de cada linha em strings com várias linhas. Sem esta opção, as âncoras correspondem ao início ou ao fim da string inteira. A opção m só tem efeito se o padrão contiver âncoras e a string tiver quebras de linha (como \n).
    • x: Modo "estendido", que ignora todos os caracteres de espaço em branco no padrão, a menos que estejam escapados ou dentro de uma classe de caracteres. Também ignora caracteres entre um # não escapado e o próximo caractere de nova linha, permitindo comentários em padrões complexos. Isso se aplica apenas a caracteres de dados; espaços em branco nunca aparecem em sequências espceiais de caracteres do padrão.
    • s: Permite que o caractere ponto (.) corresponda a qualquer caractere, incluindo quebras de linha. Esta opção só pode ser especificada no campo options.

Valor de retorno

O operador retorna um valor booleano:

  • true se houver correspondência
  • false se não houver correspondência
[ { "match" : <string>, "idx" : <num>, "captures" : <array of strings> }, ... ]

Uso

Biblioteca PCRE

A partir da versão 6.1, o MongoDB usa a biblioteca PCRE2 (Expressões Regulares Compatíveis com Perl) para implementar correspondência de padrões de expressão regular.

$regexMatch e Collation

O $regexMatch ignora qualquer collation especificada para a coleção, para o método db.collection.aggregate() e para índices (se usados).

Por exemplo, crie um coleção de exemplo com collation de força 1 (que compara apenas caracteres básicos e ignora outras diferenças, como maiúsculas/minúsculas e acentos):

db.createCollection( "myColl", { collation: { locale: "fr", strength: 1 } } )

Insira os seguintes documentos:

db.myColl.insertMany([
  { _id: 1, category: "café" },
  { _id: 2, category: "cafe" },
  { _id: 3, category: "cafE" }
])

Usando a collation da coleção, a operação a seguir faz uma correspondência sem distinção de maiúsculas/minúsculas e sem distinção de acentos:

db.myColl.aggregate( [ { $match: { category: "cafe" } } ] )

A operação retorna os seguintes 3 documentos:

{ "_id" : 1, "category" : "café" }
{ "_id" : 2, "category" : "cafe" }
{ "_id" : 3, "category" : "cafE" }

No entanto, a expressão de agregação $regexMatch ignora a collation; ou seja, o exemplo a seguir de correspondência de padrão regex faz distinção entre maiúsculas e minúsculas e acentos:

db.myColl.aggregate( [ { $addFields: { results: { $regexMatch: { input: "$category", regex: /cafe/ }  } } } ] )
db.myColl.aggregate(
  [ { $addFields: { results: { $regexMatch: { input: "$category", regex: /cafe/ }  } } } ],
  { collation: { locale: "fr", strength: 1 } }     // ignorado em $regexMatch
)

Ambas as operações retornam os seguintes resultados:

{ "_id" : 1, "category" : "café", "results" : false }
{ "_id" : 2, "category" : "cafe", "results" : true }
{ "_id" : 3, "category" : "cafE", "results" : false }

Para fazer correspondência de padrão regex sem distinção de maiúsculas/minúsculas, use a opção i.

Exemplos

$regexMatch e suas opções

Crie a coleção products com os seguintes documentos:

db.products.insertMany([
  { _id: 1, description: "Single LINE description." },
  { _id: 2, description: "First lines\nsecond line" },
  { _id: 3, description: "Many spaces before     line" },
  { _id: 4, description: "Multiple\nline descriptions" },
  { _id: 5, description: "anchors, links and hyperlinks" },
  { _id: 6, description: "métier work vocation" }
])

Por padrão, $regexMatch faz correspondência com distinção de maiúsculas/minúsculas. O exemplo a seguir faz um $regexMatch com distinção de maiúsculas/minúsculas no campo description. O padrão regex /line/ não especifica agrupamento:

db.products.aggregate([
  { $addFields: { result: { $regexMatch: { input: "$description", regex: /line/ } } } }
])

Resultado:

{ "_id" : 1, "description" : "Single LINE description.", "result" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before     line", "result" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : false }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }

O padrão regex /lin(e|k)/ especifica um agrupamento (e|k):

db.products.aggregate([
  { $addFields: { result: { $regexMatch: { input: "$description", regex: /lin(e|k)/ } } } }
])

Resultado:

{ "_id" : 1, "description" : "Single LINE description.", "result" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before     line", "result" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : true }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }

Nota: Não é permitido especificar opções simultaneamente nos campos regex e options.

Opção i

Para fazer correspondência sem distinção de maiúsculas/minúsculas, inclua a opção i no campo regex ou no campo options:

// Especificando i como parte do campo regex
{ $regexMatch: { input: "$description", regex: /line/i } }
// Especificando i no campo options
{ $regexMatch: { input: "$description", regex: /line/, options: "i" } }
{ $regexMatch: { input: "$description", regex: "line", options: "i" } }

Exemplo de correspondência sem distinção de maiúsculas/minúsculas com o padrão /line/:

db.products.aggregate([
  { $addFields: { result: { $regexMatch: { input: "$description", regex: /line/i } } } }
])

Resultado:

{ "_id" : 1, "description" : "Single LINE description.", "result" : true }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before     line", "result" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : false }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }
Opção m

Para corresponder âncoras (como ^, $) em cada linha de uma string multilinha, inclua a opção m no campo regex ou no campo options:

// Especificando m como parte do campo regex
{ $regexMatch: { input: "$description", regex: /line/m } }
// Especificando m no campo options
{ $regexMatch: { input: "$description", regex: /line/, options: "m" } }
{ $regexMatch: { input: "$description", regex: "line", options: "m" } }

Exemplo usando i e m para corresponder linhas que começam com a letra s ou S:

db.products.aggregate([
  { $addFields: { result: { $regexMatch: { input: "$description", regex: /^s/im } } } }
])

Resultado:

{ "_id" : 1, "description" : "Single LINE description.", "result" : true }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before     line", "result" : false }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : false }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : false }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }
Opção x

Para ignorar espaços em branco não escapados e comentários (delimitados por # não escapado até a próxima quebra de linha), inclua a opção x no campo options:

// Especificando x no campo options
{ $regexMatch: { input: "$description", regex: /line/, options: "x" } }
{ $regexMatch: { input: "$description", regex: "line", options: "x" } }

Exemplo com a opção x ignorando o comentário:

db.products.aggregate([
  { $addFields: { returns: { $regexMatch: { input: "$description", regex: /lin(e|k) # matches line or link/, options:"x" } } } }
])

Resultado:

{ "_id" : 1, "description" : "Single LINE description.", "returns" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "returns" : true }
{ "_id" : 3, "description" : "Many spaces before     line", "returns" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returns" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returns" : true }
{ "_id" : 6, "description" : "métier work vocation", "returns" : false }
Opção s

Para permitir que o caractere ponto (.) corresponda a qualquer caractere, incluindo quebras de linha, inclua a opção s no campo options:

// Especificando s no campo options
{ $regexMatch: { input: "$description", regex: /m.*line/, options: "s" } }
{ $regexMatch: { input: "$description", regex: "m.*line", options: "s" } }

Exemplo combinando as opções s e i:

db.products.aggregate([
  { $addFields: { returns: { $regexMatch: { input: "$description", regex:/m.*line/, options: "si"  } } } }
])

Resultado:

{ "_id" : 1, "description" : "Single LINE description.", "returns" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "returns" : false }
{ "_id" : 3, "description" : "Many spaces before     line", "returns" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returns" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returns" : false }
{ "_id" : 6, "description" : "métier work vocation", "returns" : false }

Usando $regexMatch para verificar endereços de e-mail

Crie a coleção feedback com os seguintes documentos:

db.feedback.insertMany([
  { "_id" : 1, comment: "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com"  },
  { "_id" : 2, comment: "I wanted to concatenate a string" },
  { "_id" : 3, comment: "How do I convert a date to string? cam@mongodb.com" },
  { "_id" : 4, comment: "It's just me. I'm testing.  fred@MongoDB.com" }
])

A agregação a seguir usa $regexMatch para verificar se o campo comment contém um endereço de e-mail com @mongodb.com e classifica o feedback como Employee ou External:

db.feedback.aggregate( [
   { $addFields: {
      "category": { $cond: { if:  { $regexMatch: { input: "$comment", regex: /[a-z0-9_.+-]+@mongodb.com/i } },
                             then: "Employee",
                             else: "External" } }
   } },
] )

Resultado:

{ "_id" : 1, "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com", "category" : "External" }
{ "_id" : 2, "comment" : "I wanted to concatenate a string", "category" : "External" }
{ "_id" : 3, "comment" : "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com", "category" : "Employee" }
{ "_id" : 4, "comment" : "It's just me. I'm testing.  fred@MongoDB.com", "category" : "Employee" }

Tags: mongodb expressão regular agregação $regexMatch PCRE2

Publicado em 7-14 03:33