break compile time dependencies in query compilers

This commit is contained in:
byte[] 2019-12-30 16:02:25 -05:00
parent 5163da171b
commit 0f3cb295a3
6 changed files with 193 additions and 296 deletions

View file

@ -1,7 +1,7 @@
defmodule Philomena.Comments.Query do
alias Search.Parser
def user_id_transform(_ctx, data) do
defp user_id_transform(_ctx, data) do
case Integer.parse(data) do
{int, _rest} ->
{
@ -21,7 +21,7 @@ defmodule Philomena.Comments.Query do
end
end
def author_transform(_ctx, data) do
defp author_transform(_ctx, data) do
{
:ok,
%{
@ -35,85 +35,54 @@ defmodule Philomena.Comments.Query do
}
end
def user_my_transform(%{user: %{id: id}}, "comments"),
defp user_my_transform(%{user: %{id: id}}, "comments"),
do: {:ok, %{term: %{user_id: id}}}
def user_my_transform(_ctx, _value),
defp user_my_transform(_ctx, _value),
do: {:error, "Unknown `my' value."}
int_fields = ~W(id)
date_fields = ~W(created_at)
literal_fields = ~W(image_id)
ngram_fields = ~W(body)
custom_fields = ~W(author user_id)
default_field = {"body", :ngram}
transforms = %{
"user_id" => &Philomena.Comments.Query.user_id_transform/2,
"author" => &Philomena.Comments.Query.author_transform/2
}
aliases = %{
"created_at" => "posted_at",
}
user_custom = custom_fields ++ ~W(my)
user_transforms = Map.merge(transforms, %{
"my" => &Philomena.Comments.Query.user_my_transform/2
})
mod_literal_fields = ~W(image_id user_id author fingerprint)
mod_ip_fields = ~W(ip)
mod_bool_fields = ~W(anonymous deleted)
mod_aliases = Map.merge(aliases, %{
"deleted" => "hidden_from_users"
})
mod_custom = user_custom -- ~W(author user_id)
mod_transforms = Map.drop(user_transforms, ["user_id", "author"])
@anonymous_parser Parser.parser(
int_fields: int_fields,
date_fields: date_fields,
literal_fields: literal_fields,
ngram_fields: ngram_fields,
custom_fields: custom_fields,
aliases: aliases,
default_field: default_field,
transforms: transforms
)
@user_parser Parser.parser(
int_fields: int_fields,
date_fields: date_fields,
literal_fields: literal_fields,
ngram_fields: ngram_fields,
custom_fields: user_custom,
transforms: user_transforms,
aliases: aliases,
default_field: default_field
)
@moderator_parser Parser.parser(
int_fields: int_fields,
date_fields: date_fields,
literal_fields: mod_literal_fields,
ip_fields: mod_ip_fields,
ngram_fields: ngram_fields,
bool_fields: mod_bool_fields,
custom_fields: mod_custom,
transforms: mod_transforms,
aliases: mod_aliases,
default_field: default_field
)
def parse_anonymous(context, query_string) do
Parser.parse(@anonymous_parser, query_string, context)
defp anonymous_fields do
[
int_fields: ~W(id),
date_fields: ~W(created_at),
literal_fields: ~W(image_id),
ngram_fields: ~W(body),
custom_fields: ~W(author user_id),
default_field: {"body", :ngram},
transforms: %{
"user_id" => &user_id_transform/2,
"author" => &author_transform/2
},
aliases: %{"created_at" => "posted_at"}
]
end
def parse_user(context, query_string) do
Parser.parse(@user_parser, query_string, context)
defp user_fields do
fields = anonymous_fields()
Keyword.merge(fields, [
custom_fields: fields[:custom_fields] ++ ~W(my),
transforms: Map.merge(fields[:transforms], %{"my" => &user_my_transform/2})
])
end
def parse_moderator(context, query_string) do
Parser.parse(@moderator_parser, query_string, context)
defp moderator_fields do
fields = user_fields()
Keyword.merge(fields, [
literal_fields: ~W(image_id user_id author fingerprint),
ip_fields: ~W(ip),
bool_fields: ~W(anonymous deleted),
custom_fields: fields[:custom_fields] -- ~W(author user_id),
aliases: Map.merge(fields[:aliases], %{"deleted" => "hidden_from_users"}),
transforms: Map.drop(fields[:transforms], ~W(author user_id))
])
end
defp parse(fields, context, query_string) do
fields
|> Parser.parser()
|> Parser.parse(query_string, context)
end
def compile(user, query_string) do
@ -121,13 +90,13 @@ defmodule Philomena.Comments.Query do
case user do
nil ->
parse_anonymous(%{user: nil}, query_string)
parse(anonymous_fields(), %{user: nil}, query_string)
%{role: role} when role in ~W(user assistant) ->
parse_user(%{user: user}, query_string)
parse(user_fields(), %{user: user}, query_string)
%{role: role} when role in ~W(moderator admin) ->
parse_moderator(%{user: user}, query_string)
parse(moderator_fields(), %{user: user}, query_string)
_ ->
raise ArgumentError, "Unknown user role."

View file

@ -1,27 +1,24 @@
defmodule Philomena.Galleries.Query do
alias Search.Parser
int_fields = ~W(id image_count watcher_count)
literal_fields = ~W(title user image_ids watcher_ids)
date_fields = ~W(created_at updated_at)
ngram_fields = ~W(description)
default_field = {"title", :term}
aliases = %{
"user" => "creator"
}
@gallery_parser Parser.parser(
int_fields: int_fields,
literal_fields: literal_fields,
date_fields: date_fields,
ngram_fields: ngram_fields,
default_field: default_field,
aliases: aliases
)
defp fields do
[
int_fields: ~W(id image_count watcher_count),
literal_fields: ~W(title user image_ids watcher_ids),
date_fields: ~W(created_at updated_at),
ngram_fields: ~W(description),
default_field: {"title", :term},
aliases: %{
"user" => "creator"
}
]
end
def compile(query_string) do
query_string = query_string || ""
Parser.parse(@gallery_parser, query_string)
fields()
|> Parser.parser()
|> Parser.parse(query_string)
end
end

View file

@ -2,28 +2,28 @@ defmodule Philomena.Images.Query do
alias Search.Parser
alias Philomena.Repo
def gallery_id_transform(_ctx, value),
defp gallery_id_transform(_ctx, value),
do: {:ok, %{nested: %{path: :galleries, query: %{term: %{"galleries.id" => value}}}}}
def user_my_transform(%{user: %{id: id}}, "faves"),
defp user_my_transform(%{user: %{id: id}}, "faves"),
do: {:ok, %{term: %{favourited_by_user_ids: id}}}
def user_my_transform(%{user: %{id: id}}, "upvotes"),
defp user_my_transform(%{user: %{id: id}}, "upvotes"),
do: {:ok, %{term: %{upvoter_ids: id}}}
def user_my_transform(%{user: %{id: id}}, "downvotes"),
defp user_my_transform(%{user: %{id: id}}, "downvotes"),
do: {:ok, %{term: %{downvoter_ids: id}}}
def user_my_transform(%{user: %{id: id}}, "uploads"),
defp user_my_transform(%{user: %{id: id}}, "uploads"),
do: {:ok, %{term: %{true_uploader_id: id}}}
def user_my_transform(%{user: %{id: id}}, "hidden"),
defp user_my_transform(%{user: %{id: id}}, "hidden"),
do: {:ok, %{term: %{hidden_by_user_ids: id}}}
def user_my_transform(%{watch: true}, "watched"),
defp user_my_transform(%{watch: true}, "watched"),
do: {:error, "Recursive watchlists are not allowed."}
def user_my_transform(%{user: user} = ctx, "watched") do
defp user_my_transform(%{user: user} = ctx, "watched") do
ctx = Map.merge(ctx, %{watch: true})
tag_include = %{terms: %{tag_ids: user.watched_tag_ids}}
@ -49,101 +49,66 @@ defmodule Philomena.Images.Query do
{:ok, %{bool: %{should: should, must_not: must_not}}}
end
def user_my_transform(_ctx, _value),
defp user_my_transform(_ctx, _value),
do: {:error, "Unknown `my' value."}
defp invalid_filter_guard(ctx, search_string) do
case Philomena.Images.Query.parse_user(ctx, Search.String.normalize(search_string)) do
case parse(user_fields(), ctx, Search.String.normalize(search_string)) do
{:ok, query} -> query
_error -> %{match_all: %{}}
end
end
int_fields = ~W(id width height comment_count score upvotes downvotes faves uploader_id faved_by_id tag_count)
float_fields = ~W(aspect_ratio wilson_score)
date_fields = ~W(created_at updated_at first_seen_at)
literal_fields = ~W(faved_by orig_sha512_hash sha512_hash uploader source_url original_format)
ngram_fields = ~W(description)
custom_fields = ~W(gallery_id)
default_field = {"namespaced_tags.name", :term}
transforms = %{
"gallery_id" => &Philomena.Images.Query.gallery_id_transform/2
}
aliases = %{
"faved_by" => "favourited_by_users",
"faved_by_id" => "favourited_by_user_ids"
}
user_custom = custom_fields ++ ~W(my)
user_transforms = Map.merge(transforms, %{
"my" => &Philomena.Images.Query.user_my_transform/2
})
mod_int_fields = int_fields ++ ~W(upvoted_by_id downvoted_by_id true_uploader_id hidden_by_id deleted_by_user_id)
mod_literal_fields = literal_fields ++ ~W(fingerprint upvoted_by downvoted_by true_uploader hidden_by deleted_by_user)
mod_ip_fields = ~W(ip)
mod_bool_fields = ~W(deleted)
mod_aliases = Map.merge(aliases, %{
"upvoted_by" => "upvoters",
"downvoted_by" => "downvoters",
"upvoted_by_id" => "upvoter_ids",
"downvoted_by_id" => "downvoter_ids",
"hidden_by" => "hidden_by_users",
"hidden_by_id" => "hidden_by_user_ids",
"deleted" => "hidden_from_users"
})
@anonymous_parser Parser.parser(
int_fields: int_fields,
float_fields: float_fields,
date_fields: date_fields,
literal_fields: literal_fields,
ngram_fields: ngram_fields,
custom_fields: custom_fields,
transforms: transforms,
aliases: aliases,
default_field: default_field
)
@user_parser Parser.parser(
int_fields: int_fields,
float_fields: float_fields,
date_fields: date_fields,
literal_fields: literal_fields,
ngram_fields: ngram_fields,
custom_fields: user_custom,
transforms: user_transforms,
aliases: aliases,
default_field: default_field
)
@moderator_parser Parser.parser(
int_fields: mod_int_fields,
float_fields: float_fields,
date_fields: date_fields,
literal_fields: mod_literal_fields,
ip_fields: mod_ip_fields,
ngram_fields: ngram_fields,
bool_fields: mod_bool_fields,
custom_fields: user_custom,
transforms: user_transforms,
aliases: mod_aliases,
default_field: default_field
)
def parse_anonymous(context, query_string) do
Parser.parse(@anonymous_parser, query_string, context)
defp anonymous_fields do
[
int_fields: ~W(id width height comment_count score upvotes downvotes faves uploader_id faved_by_id tag_count),
float_fields: ~W(aspect_ratio wilson_score),
date_fields: ~W(created_at updated_at first_seen_at),
literal_fields: ~W(faved_by orig_sha512_hash sha512_hash uploader source_url original_format),
ngram_fields: ~W(description),
custom_fields: ~W(gallery_id),
default_field: {"namespaced_tags.name", :term},
transforms: %{"gallery_id" => &gallery_id_transform/2},
aliases: %{
"faved_by" => "favourited_by_users",
"faved_by_id" => "favourited_by_user_ids"
}
]
end
def parse_user(context, query_string) do
Parser.parse(@user_parser, query_string, context)
defp user_fields do
fields = anonymous_fields()
Keyword.merge(fields, [
custom_fields: fields[:custom_fields] ++ ~W(my),
transforms: Map.merge(fields[:transforms], %{"my" => &user_my_transform/2})
])
end
def parse_moderator(context, query_string) do
Parser.parse(@moderator_parser, query_string, context)
defp moderator_fields do
fields = user_fields()
Keyword.merge(fields, [
int_fields: fields[:int_fields] ++ ~W(upvoted_by_id downvoted_by_id true_uploader_id hidden_by_id deleted_by_user_id),
literal_fields: fields[:literal_fields] ++ ~W(fingerprint upvoted_by downvoted_by true_uploader hidden_by deleted_by_user),
ip_fields: ~W(ip),
bool_fields: ~W(deleted),
aliases: Map.merge(fields[:aliases], %{
"upvoted_by" => "upvoters",
"downvoted_by" => "downvoters",
"upvoted_by_id" => "upvoter_ids",
"downvoted_by_id" => "downvoter_ids",
"hidden_by" => "hidden_by_users",
"hidden_by_id" => "hidden_by_user_ids",
"deleted" => "hidden_from_users"
})
])
end
defp parse(fields, context, query_string) do
fields
|> Parser.parser()
|> Parser.parse(query_string, context)
end
def compile(user, query_string, watch \\ false) do
@ -151,13 +116,13 @@ defmodule Philomena.Images.Query do
case user do
nil ->
parse_anonymous(%{user: nil, watch: watch}, query_string)
parse(anonymous_fields(), %{user: nil, watch: watch}, query_string)
%{role: role} when role in ~W(user assistant) ->
parse_user(%{user: user, watch: watch}, query_string)
parse(user_fields(), %{user: user, watch: watch}, query_string)
%{role: role} when role in ~W(moderator admin) ->
parse_moderator(%{user: user, watch: watch}, query_string)
parse(moderator_fields(), %{user: user, watch: watch}, query_string)
_ ->
raise ArgumentError, "Unknown user role."

View file

@ -1,7 +1,7 @@
defmodule Philomena.Posts.Query do
alias Search.Parser
def user_id_transform(_ctx, data) do
defp user_id_transform(_ctx, data) do
case Integer.parse(data) do
{int, _rest} ->
{
@ -21,7 +21,7 @@ defmodule Philomena.Posts.Query do
end
end
def author_transform(_ctx, data) do
defp author_transform(_ctx, data) do
{
:ok,
%{
@ -35,77 +35,52 @@ defmodule Philomena.Posts.Query do
}
end
def user_my_transform(%{user: %{id: id}}, "posts"),
defp user_my_transform(%{user: %{id: id}}, "posts"),
do: {:ok, %{term: %{user_id: id}}}
def user_my_transform(_ctx, _value),
defp user_my_transform(_ctx, _value),
do: {:error, "Unknown `my' value."}
int_fields = ~W(id)
date_fields = ~W(created_at updated_at)
literal_fields = ~W(forum_id topic_id)
ngram_fields = ~W(body subject)
custom_fields = ~W(author user_id)
default_field = {"body", :ngram}
transforms = %{
"user_id" => &Philomena.Posts.Query.user_id_transform/2,
"author" => &Philomena.Posts.Query.author_transform/2
}
user_custom = custom_fields ++ ~W(my)
user_transforms = Map.merge(transforms, %{
"my" => &Philomena.Posts.Query.user_my_transform/2
})
mod_literal_fields = ~W(forum_id topic_id user_id author fingerprint)
mod_ip_fields = ~W(ip)
mod_bool_fields = ~W(anonymous deleted)
mod_custom = user_custom -- ~W(author user_id)
mod_transforms = Map.drop(user_transforms, ["user_id", "author"])
@anonymous_parser Parser.parser(
int_fields: int_fields,
date_fields: date_fields,
literal_fields: literal_fields,
ngram_fields: ngram_fields,
custom_fields: custom_fields,
default_field: default_field,
transforms: transforms
)
@user_parser Parser.parser(
int_fields: int_fields,
date_fields: date_fields,
literal_fields: literal_fields,
ngram_fields: ngram_fields,
custom_fields: user_custom,
transforms: user_transforms,
default_field: default_field
)
@moderator_parser Parser.parser(
int_fields: int_fields,
date_fields: date_fields,
literal_fields: mod_literal_fields,
ip_fields: mod_ip_fields,
ngram_fields: ngram_fields,
bool_fields: mod_bool_fields,
custom_fields: mod_custom,
transforms: mod_transforms,
default_field: default_field
)
def parse_anonymous(context, query_string) do
Parser.parse(@anonymous_parser, query_string, context)
defp anonymous_fields do
[
int_fields: ~W(id),
date_fields: ~W(created_at updated_at),
literal_fields: ~W(forum_id topic_id),
ngram_fields: ~W(body subject),
custom_fields: ~W(author user_id),
default_field: {"body", :ngram},
transforms: %{
"user_id" => &user_id_transform/2,
"author" => &author_transform/2
}
]
end
def parse_user(context, query_string) do
Parser.parse(@user_parser, query_string, context)
defp user_fields do
fields = anonymous_fields()
Keyword.merge(fields, [
custom_fields: fields[:custom_fields] ++ ~W(my),
transforms: Map.merge(fields[:transforms], %{"my" => &user_my_transform/2})
])
end
def parse_moderator(context, query_string) do
Parser.parse(@moderator_parser, query_string, context)
defp moderator_fields do
fields = user_fields()
Keyword.merge(fields, [
literal_fields: ~W(forum_id topic_id user_id author fingerprint),
ip_fields: ~W(ip),
bool_fields: ~W(anonymous deleted),
custom_fields: fields[:custom_fields] -- ~W(author user_id),
transforms: Map.drop(fields[:transforms], ["user_id", "author"])
])
end
defp parse(fields, context, query_string) do
fields
|> Parser.parser()
|> Parser.parse(query_string, context)
end
def compile(user, query_string) do
@ -113,13 +88,13 @@ defmodule Philomena.Posts.Query do
case user do
nil ->
parse_anonymous(%{user: nil}, query_string)
parse(anonymous_fields(), %{user: nil}, query_string)
%{role: role} when role in ~W(user assistant) ->
parse_user(%{user: user}, query_string)
parse(user_fields(), %{user: user}, query_string)
%{role: role} when role in ~W(moderator admin) ->
parse_moderator(%{user: user}, query_string)
parse(moderator_fields(), %{user: user}, query_string)
_ ->
raise ArgumentError, "Unknown user role."

View file

@ -1,25 +1,21 @@
defmodule Philomena.Reports.Query do
alias Search.Parser
int_fields = ~W(id image_id)
date_fields = ~W(created_at)
literal_fields = ~W(state user user_id admin admin_id reportable_type reportable_id fingerprint)
ip_fields = ~W(ip)
bool_fields = ~W(open)
ngram_fields = ~W(reason)
default_field = {"reason", :ngram}
@parser Parser.parser(
int_fields: int_fields,
date_fields: date_fields,
literal_fields: literal_fields,
ip_fields: ip_fields,
bool_fields: bool_fields,
ngram_fields: ngram_fields,
default_field: default_field
)
defp fields do
[
int_fields: ~W(id image_id),
date_fields: ~W(created_at),
literal_fields: ~W(state user user_id admin admin_id reportable_type reportable_id fingerprint),
ip_fields: ~W(ip),
bool_fields: ~W(open),
ngram_fields: ~W(reason),
default_field: {"reason", :ngram}
]
end
def compile(query_string) do
Parser.parse(@parser, query_string || "", %{})
fields()
|> Parser.parser()
|> Parser.parse(query_string || "", %{})
end
end

View file

@ -1,29 +1,24 @@
defmodule Philomena.Tags.Query do
alias Search.Parser
int_fields = ~W(id images)
literal_fields = ~W(slug name name_in_namespace namespace implies alias_of implied_by aliases category analyzed_name)
bool_fields = ~W(aliased)
ngram_fields = ~W(description short_description)
default_field = {"analyzed_name", :ngram}
aliases = %{
"implies" => "implied_tags",
"implied_by" => "implied_by_tags",
"alias_of" => "aliased_tag"
}
@tag_parser Parser.parser(
int_fields: int_fields,
literal_fields: literal_fields,
bool_fields: bool_fields,
ngram_fields: ngram_fields,
default_field: default_field,
aliases: aliases
)
defp fields do
[
int_fields: ~W(id images),
literal_fields: ~W(slug name name_in_namespace namespace implies alias_of implied_by aliases category analyzed_name),
bool_fields: ~W(aliased),
ngram_fields: ~W(description short_description),
default_field: {"analyzed_name", :ngram},
aliases: %{
"implies" => "implied_tags",
"implied_by" => "implied_by_tags",
"alias_of" => "aliased_tag"
}
]
end
def compile(query_string) do
query_string = query_string || ""
Parser.parse(@tag_parser, query_string)
fields()
|> Parser.parser()
|> Parser.parse(query_string || "")
end
end