mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-02-21 12:53:11 +01:00
add macro api
This commit is contained in:
parent
1ad4d1c574
commit
c66fe0ca39
3 changed files with 399 additions and 253 deletions
8
lib/philomena/images/query.ex
Normal file
8
lib/philomena/images/query.ex
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
defmodule Philomena.Images.Query do
|
||||||
|
use Philomena.Search.Lexer,
|
||||||
|
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(namespaced_tags.name faved_by orig_sha512_hash sha512_hash uploader source_url original_format),
|
||||||
|
ngram_fields: ~W(description)
|
||||||
|
end
|
|
@ -13,4 +13,18 @@ defmodule Philomena.Search.Helpers do
|
||||||
int_val
|
int_val
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def full_choice(combinator \\ empty(), choices)
|
||||||
|
|
||||||
|
def full_choice(combinator, []) do
|
||||||
|
combinator |> eos()
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_choice(combinator, [choice]) do
|
||||||
|
combinator |> concat(choice)
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_choice(combinator, choices) do
|
||||||
|
choice(combinator, choices)
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -1,4 +1,15 @@
|
||||||
defmodule Philomena.Search.Lexer do
|
defmodule Philomena.Search.Lexer do
|
||||||
|
defmacro __using__(opts) do
|
||||||
|
literal_fields = Keyword.get(opts, :literal, [])
|
||||||
|
ngram_fields = Keyword.get(opts, :ngram, [])
|
||||||
|
bool_fields = Keyword.get(opts, :bool, [])
|
||||||
|
date_fields = Keyword.get(opts, :date, [])
|
||||||
|
float_fields = Keyword.get(opts, :float, [])
|
||||||
|
int_fields = Keyword.get(opts, :int, [])
|
||||||
|
ip_fields = Keyword.get(opts, :ip, [])
|
||||||
|
custom_fields = Keyword.get(opts, :custom, [])
|
||||||
|
|
||||||
|
quote location: :keep do
|
||||||
import NimbleParsec
|
import NimbleParsec
|
||||||
import Philomena.Search.Helpers
|
import Philomena.Search.Helpers
|
||||||
|
|
||||||
|
@ -228,23 +239,62 @@ defmodule Philomena.Search.Lexer do
|
||||||
relative_date
|
relative_date
|
||||||
])
|
])
|
||||||
|
|
||||||
|
eq = choice([string(":"), string(".eq:")]) |> unwrap_and_tag(:eq)
|
||||||
|
lt = string(".lt:") |> unwrap_and_tag(:lt)
|
||||||
|
lte = string(".lte:") |> unwrap_and_tag(:lte)
|
||||||
|
gt = string(".gt:") |> unwrap_and_tag(:gt)
|
||||||
|
gte = string(".gte:") |> unwrap_and_tag(:gte)
|
||||||
|
|
||||||
|
range_relation =
|
||||||
|
choice([
|
||||||
|
eq,
|
||||||
|
lt,
|
||||||
|
lte,
|
||||||
|
gt,
|
||||||
|
gte
|
||||||
|
])
|
||||||
|
|
||||||
boost = ignore(string("^")) |> unwrap_and_tag(number, :boost)
|
boost = ignore(string("^")) |> unwrap_and_tag(number, :boost)
|
||||||
fuzz = ignore(string("~")) |> unwrap_and_tag(number, :fuzz)
|
fuzz = ignore(string("~")) |> unwrap_and_tag(number, :fuzz)
|
||||||
|
|
||||||
quot = string("\"")
|
quot = string("\"")
|
||||||
|
|
||||||
quoted_term =
|
bool_value =
|
||||||
ignore(quot)
|
full_choice(unquote(for f <- bool_fields, do: [string: f]))
|
||||||
|> choice([
|
|> concat(eq)
|
||||||
ignore(string("\\")) |> string("\""),
|
|> concat(bool)
|
||||||
ignore(string("\\")) |> string("\\"),
|
|
||||||
string("\\") |> utf8_char([]),
|
date_value =
|
||||||
utf8_char(not: ?")
|
full_choice(unquote(for f <- date_fields, do: [string: f]))
|
||||||
|
|> concat(range_relation)
|
||||||
|
|> concat(date)
|
||||||
|
|
||||||
|
float_value =
|
||||||
|
full_choice(unquote(for f <- float_fields, do: [string: f]))
|
||||||
|
|> concat(range_relation)
|
||||||
|
|> concat(number)
|
||||||
|
|
||||||
|
int_value =
|
||||||
|
full_choice(unquote(for f <- int_fields, do: [string: f]))
|
||||||
|
|> concat(range_relation)
|
||||||
|
|> concat(int)
|
||||||
|
|
||||||
|
ip_value =
|
||||||
|
full_choice(unquote(for f <- ip_fields, do: [string: f]))
|
||||||
|
|> concat(eq)
|
||||||
|
|> concat(ip_address)
|
||||||
|
|
||||||
|
numeric =
|
||||||
|
choice([
|
||||||
|
bool_value,
|
||||||
|
date_value,
|
||||||
|
float_value,
|
||||||
|
int_value,
|
||||||
|
ip_value
|
||||||
])
|
])
|
||||||
|> times(min: 1)
|
|
||||||
|> ignore(quot)
|
quoted_numeric =
|
||||||
|> reduce({List, :to_string, []})
|
ignore(quot) |> concat(numeric) |> ignore(quot)
|
||||||
|> unwrap_and_tag(:term)
|
|
||||||
|
|
||||||
stop_words =
|
stop_words =
|
||||||
choice([
|
choice([
|
||||||
|
@ -259,20 +309,93 @@ defmodule Philomena.Search.Lexer do
|
||||||
])
|
])
|
||||||
|
|
||||||
defcombinatorp(
|
defcombinatorp(
|
||||||
:simple_term,
|
:text,
|
||||||
lookahead_not(stop_words)
|
lookahead_not(stop_words)
|
||||||
|> choice([
|
|> choice([
|
||||||
string("\\") |> utf8_char([]),
|
string("\\") |> utf8_char([]),
|
||||||
string("(") |> parsec(:simple_term) |> string(")"),
|
string("(") |> parsec(:text) |> string(")"),
|
||||||
utf8_char([])
|
utf8_char([])
|
||||||
])
|
])
|
||||||
|> times(min: 1)
|
|> times(min: 1)
|
||||||
|
|> reduce({List, :to_string, []})
|
||||||
|
|> unwrap_and_tag(:text)
|
||||||
)
|
)
|
||||||
|
|
||||||
unquoted_term =
|
text = parsec(:text)
|
||||||
parsec(:simple_term)
|
|
||||||
|
quoted_text =
|
||||||
|
choice([
|
||||||
|
ignore(string("\\")) |> string("\""),
|
||||||
|
ignore(string("\\")) |> string("\\"),
|
||||||
|
string("\\") |> utf8_char([]),
|
||||||
|
utf8_char(not: ?")
|
||||||
|
])
|
||||||
|
|> times(min: 1)
|
||||||
|> reduce({List, :to_string, []})
|
|> reduce({List, :to_string, []})
|
||||||
|> unwrap_and_tag(:term)
|
|> unwrap_and_tag(:text)
|
||||||
|
|
||||||
|
literal =
|
||||||
|
full_choice(unquote(for f <- literal_fields, do: [string: f]))
|
||||||
|
|> ignore(eq)
|
||||||
|
|> concat(text)
|
||||||
|
|> tag(:literal)
|
||||||
|
|
||||||
|
ngram =
|
||||||
|
full_choice(unquote(for f <- ngram_fields, do: [string: f]))
|
||||||
|
|> ignore(eq)
|
||||||
|
|> concat(text)
|
||||||
|
|> tag(:ngram)
|
||||||
|
|
||||||
|
custom =
|
||||||
|
full_choice(unquote(for f <- custom_fields, do: [string: f]))
|
||||||
|
|> ignore(string(":"))
|
||||||
|
|> concat(text)
|
||||||
|
|
||||||
|
quoted_literal =
|
||||||
|
ignore(quot)
|
||||||
|
|> full_choice(unquote(for f <- literal_fields, do: [string: f]))
|
||||||
|
|> ignore(eq)
|
||||||
|
|> concat(quoted_text)
|
||||||
|
|> ignore(quot)
|
||||||
|
|> tag(:literal)
|
||||||
|
|
||||||
|
quoted_ngram =
|
||||||
|
ignore(quot)
|
||||||
|
|> full_choice(unquote(for f <- ngram_fields, do: [string: f]))
|
||||||
|
|> ignore(eq)
|
||||||
|
|> concat(quoted_text)
|
||||||
|
|> ignore(quot)
|
||||||
|
|> tag(:ngram)
|
||||||
|
|
||||||
|
quoted_custom =
|
||||||
|
ignore(quot)
|
||||||
|
|> full_choice(unquote(for f <- custom_fields, do: [string: f]))
|
||||||
|
|> ignore(string(":"))
|
||||||
|
|> concat(quoted_text)
|
||||||
|
|> ignore(quot)
|
||||||
|
|> tag(:custom)
|
||||||
|
|
||||||
|
default =
|
||||||
|
text
|
||||||
|
|> tag(:default)
|
||||||
|
|
||||||
|
quoted_default =
|
||||||
|
quoted_text
|
||||||
|
|> tag(:default)
|
||||||
|
|
||||||
|
term =
|
||||||
|
choice([
|
||||||
|
quoted_numeric,
|
||||||
|
quoted_literal,
|
||||||
|
quoted_ngram,
|
||||||
|
quoted_custom,
|
||||||
|
quoted_default,
|
||||||
|
numeric,
|
||||||
|
literal,
|
||||||
|
ngram,
|
||||||
|
custom,
|
||||||
|
default
|
||||||
|
])
|
||||||
|
|
||||||
outer =
|
outer =
|
||||||
choice([
|
choice([
|
||||||
|
@ -284,8 +407,7 @@ defmodule Philomena.Search.Lexer do
|
||||||
boost,
|
boost,
|
||||||
fuzz,
|
fuzz,
|
||||||
space,
|
space,
|
||||||
quoted_term,
|
term
|
||||||
unquoted_term
|
|
||||||
])
|
])
|
||||||
|
|
||||||
search =
|
search =
|
||||||
|
@ -293,4 +415,6 @@ defmodule Philomena.Search.Lexer do
|
||||||
|> eos()
|
|> eos()
|
||||||
|
|
||||||
defparsec(:search, search)
|
defparsec(:search, search)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue