Support negated glob filters everywhere

This commit is contained in:
Uku Taht 2021-08-18 15:17:49 +03:00
parent 49214eaff8
commit 3d3601c332
5 changed files with 116 additions and 2 deletions

View File

@ -74,6 +74,10 @@ defmodule Plausible.Stats.Aggregate do
{:matches, expr} ->
regex = page_regex(expr)
{"match(p, ?)", regex}
{:does_not_match, expr} ->
regex = page_regex(expr)
{"not(match(p, ?))", regex}
end
time_query = "

View File

@ -47,6 +47,10 @@ defmodule Plausible.Stats.Base do
regex = page_regex(glob_expr)
from(e in q, where: fragment("match(?, ?)", e.pathname, ^regex))
{:does_not_match, glob_expr} ->
regex = page_regex(glob_expr)
from(e in q, where: fragment("not(match(?, ?))", e.pathname, ^regex))
{:member, list} ->
from(e in q, where: e.pathname in ^list)
@ -174,7 +178,13 @@ defmodule Plausible.Stats.Base do
{:matches, expr} ->
regex = page_regex(expr)
from(s in sessions_q, where: fragment("match(?, ?)", ^prop_name, ^regex))
prop_name = String.to_existing_atom(prop_name)
from(s in sessions_q, where: fragment("match(?, ?)", field(s, ^prop_name), ^regex))
{:does_not_match, expr} ->
regex = page_regex(expr)
prop_name = String.to_existing_atom(prop_name)
from(s in sessions_q, where: fragment("not(match(?, ?))", field(s, ^prop_name), ^regex))
nil ->
sessions_q

View File

@ -171,7 +171,9 @@ defmodule Plausible.Stats.Query do
query
filter ->
put_filter(query, "visit:entry_page", filter)
query
|> put_filter("event:page", nil)
|> put_filter("visit:entry_page", filter)
end
end
@ -216,6 +218,7 @@ defmodule Plausible.Stats.Query do
cond do
is_list && is_glob -> raise "Not implemented"
is_negated && is_glob -> {key, {:does_not_match, val}}
key == "event:goal" -> {key, parse_goal_filter(val)}
is_list -> {key, {:member, String.split(val, "|")}}
is_glob -> {key, {:matches, val}}

View File

@ -1334,5 +1334,65 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
]
}
end
test "negated glob filter for pages", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
pathname: "/blog/ignore",
domain: site.domain
),
build(:pageview,
pathname: "/blog",
domain: site.domain
),
build(:pageview,
pathname: "/plausible.io",
domain: site.domain
)
])
conn =
get(conn, "/api/v1/stats/breakdown", %{
"site_id" => site.domain,
"property" => "event:page",
"filters" => "event:page!=/blog**"
})
assert json_response(conn, 200) == %{
"results" => [
%{"page" => "/plausible.io", "visitors" => 1}
]
}
end
test "negated glob filter for sources", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
pathname: "/blog/ignore",
referrer_source: "Should not show"
),
build(:pageview,
pathname: "/blog",
referrer_source: "Should not show"
),
build(:pageview,
pathname: "/plausible.io",
referrer_source: "Google"
)
])
conn =
get(conn, "/api/v1/stats/breakdown", %{
"site_id" => site.domain,
"property" => "visit:source",
"filters" => "event:page!=/blog**"
})
assert json_response(conn, 200) == %{
"results" => [
%{"source" => "Google", "visitors" => 1}
]
}
end
end
end

View File

@ -797,5 +797,42 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
assert first == %{"date" => "2021-01-01", "visitors" => 2}
assert second == %{"date" => "2021-01-02", "visitors" => 1}
end
test "filter with negated glob for pages", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
pathname: "/",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
pathname: "/blog",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
pathname: "/plausible.io",
timestamp: ~N[2021-01-02 00:00:00]
),
build(:pageview,
pathname: "/",
timestamp: ~N[2021-01-02 00:00:00]
),
build(:pageview,
pathname: "/blog/ignore",
timestamp: ~N[2021-01-02 00:00:00]
)
])
conn =
get(conn, "/api/v1/stats/timeseries", %{
"site_id" => site.domain,
"period" => "month",
"date" => "2021-01-01",
"filters" => "event:page!=/blog**"
})
%{"results" => [first, second | _rest]} = json_response(conn, 200)
assert first == %{"date" => "2021-01-01", "visitors" => 1}
assert second == %{"date" => "2021-01-02", "visitors" => 2}
end
end
end