mongodb aggregate - сопоставить значения регулярного выражения массива $ nin - PullRequest
0 голосов
/ 13 июля 2020

Должен работать в пн go версия 3.4
Привет, В рамках агрегирования соответствующих тегов я хотел бы вернуть теги, которые имеют script_url, не содержащееся в whiteList массив.
Дело в том, что я хочу сравнить script_url с регулярным выражением значений массива.
У меня есть этот прогноз:

{
    "script_url" : "www.analytics.com/path/file-7.js",
    "whiteList" : [ 
        null, 
        "www.analytics.com/path/*", 
        "www.analytics.com/path/.*", 
        "www.analytics.com/path/file-6.js", 
        "www.maps.com/*", 
        "www.maps.com/.*"
    ]
}

Этот $match сравнивает script_url с точными whiteList значениями. Таким образом, документ, указанный выше, проходит, когда он не должен, поскольку он имеет www.analytics.com/path/.* in whiteList

{
    "$match": {
        "script_url": {"$nin": ["$whiteList"]}
    }
}

Как мне сопоставить script_url со значениями регулярного выражения whiteList?

update

Мне удалось достичь этого этапа в моей агрегации:

{
    "script_url" : "www.asaf-test.com/path/file-1.js",
    "whiteList" : [ 
        "http://sd.bla.com/bla/878/676.js", 
        "www.asaf-test.com/path/*"
    ],
    "whiteListRegex" : [ 
        "/http:\/\/sd\.bla\.com\/bla\/878\/676\.js/", 
        "/www\.asaf-test\.com\/path\/.*/"
    ]
}

Но $match не фильтрует это script_url, как предполагалось, потому что он сравнивает литерал строки и не приводит значения массива к регулярным выражениям значениям. Есть ли способ преобразовать значения массива в Regex значения в $map, используя v3.4 ?

1 Ответ

2 голосов
/ 15 июля 2020

Я знаю, что вы специально упомянули v3.4, но я не могу найти решение, чтобы заставить его работать с v3.4.

Так что для других, у которых меньше ограничений и которые могут использовать v4.2 это одно из решений.

Только для версии 4.2 или более поздней

Хитрость заключается в том, чтобы использовать $filter на whitelist, используя $regexMatch (доступно начиная с v4. 2), и если фильтрованный массив пуст, это означает, что script_url ничего не соответствует в whitelist

db.collection.aggregate([
  {
    $match: {
      $expr: {
        $eq: [
          {
            $filter: {
              input: "$whiteList",
              cond: {
                $regexMatch: { input: "$script_url", regex: "$$this" }
              }
            }
          },
          []
        ]
      }
    }
  }
])

Mon go Playground

Также можно использовать $reduce вместо $filter

db.collection.aggregate([
  {
    $match: {
      $expr: {
        $not: {
          $reduce: {
            input: "$whiteList",
            initialValue: false,
            in: {
              $or: [
                {
                  $regexMatch: { input: "$script_url", regex: "$$this" }
                },
                "$$value"
              ]
            }
          }
        }
      }
    }
  }
])

Пн go Детская площадка

...