MongoDb - Агрегация с использванием регулярных выражений

В БД хранится журнал запросов. У каждой записи есть поле user_agent. Пример данных:

[
  {"user_agent": "myapp v1.1(10)"},
  {"user_agent": "myapp v2.2(20)"},
  {"user_agent": "myapp v3.3(30)"},
  {"user_agent": "myapp v1.1(10) DEV"},
  {"user_agent": "xxxx"},
  {"user_agent": "yyyyy"},
  {"user_agent": "zzzz"}
]

Нужно через регулярное выражение выдрать номер версии и вывести кол-во записей для каждой версии.

введите сюда описание изображения

Пример результата:

Версия Кол-во записей
1.1(10) 2
2.2(20) 1
3.3(30) 1
Другие (не подходят под регулярку) 3

Пока получилось сделать только подсчёт по useragent-ам:

db.collection.aggregate([
  {
    "$match": {}
  },
  {
    "$group": {
      "_id": "$user_agent",
      "count": {
        "$sum": 1
      }
    }
  },
  {
    "$sort": {
      "_id": 1
    }
  }
])

Демо: https://mongoplayground.net/p/kIWnHKX8JQ7

А как сгруппировать по подстроке в регулярном выражении?


Ответы (1 шт):

Автор решения: ksa

Нужно через регулярное выражение выдрать номер версии и вывести кол-во записей для каждой версии.

Как вариант - выполнить преобразование полей $project, применив оператор $function. https://www.mydbops.com/blog/mongodb-custom-aggregation-expressions

Типа вот такого...

db.collection.aggregate([
  {
    $project: {
      "user_agent": {
        $function: { 
          body: function(v){return v.match(/[\d.()]+/)[0];},
          args: ["$user_agent"],
          lang: "js"
        }
      }
    }
  }
])

После этого можно будет выполнять группировку.

Но возможно ты столкнешься с некими ограничениями... Оператор $function достаточно "свежий" и в твоей Монге его может не быть. Так же, возможно, его применение может потребовать некоторых разрешений в настройках...

Так же всегда предупреждают что оператор $function довольно затратный по быстродействию...

→ Ссылка