From fe69b708db194cba2e4afafea33cb6eec045a597 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 25 Aug 2019 23:12:44 -0400 Subject: [PATCH] parser --- lib/philomena/search/lexer.ex | 11 ++++-- lib/philomena/search/parser.ex | 61 ++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/lib/philomena/search/lexer.ex b/lib/philomena/search/lexer.ex index d11ed471..07efd0f7 100644 --- a/lib/philomena/search/lexer.ex +++ b/lib/philomena/search/lexer.ex @@ -259,8 +259,15 @@ defmodule Philomena.Search.Lexer do gte ]) - boost = ignore(string("^")) |> unwrap_and_tag(number, :boost) - fuzz = ignore(string("~")) |> unwrap_and_tag(number, :fuzz) + boost = + string("^") + |> unwrap_and_tag(:boost) + |> concat(number) + + fuzz = + string("~") + |> unwrap_and_tag(:fuzz) + |> concat(number) quot = string("\"") diff --git a/lib/philomena/search/parser.ex b/lib/philomena/search/parser.ex index 5f13d07e..ed27e0cf 100644 --- a/lib/philomena/search/parser.ex +++ b/lib/philomena/search/parser.ex @@ -52,7 +52,7 @@ defmodule Philomena.Search.Parser do defp search_boost(ctx, tokens) do case search_not(ctx, tokens) do - {child, [{:boost, _}, {:float, value} | r_tokens]} -> + {child, [{:boost, _}, {:number, value} | r_tokens]} -> {%{function_score: %{query: child, boost_factor: value}}, r_tokens} {child, rest} -> @@ -92,23 +92,64 @@ defmodule Philomena.Search.Parser do defp search_group(ctx, tokens), do: search_fuzz(ctx, tokens) # - # Term fuzzing + # Terms and term fuzzing # - defp search_fuzz(ctx, tokens) do - search_term(ctx, tokens) + defp search_fuzz(%{default_field: default_field} = ctx, tokens) do + case tokens do + [{:int_field, field}, {:eq, _}, {:int, value}, {:fuzz, _}, {:number, fuzz} | r_tokens] -> + {%{range: %{field => %{gte: trunc(value - fuzz), lte: trunc(value + fuzz)}}}, r_tokens} + [{:float_field, field}, {:eq, _}, {:float, value}, {:fuzz, _}, {:number, fuzz} | r_tokens] -> + {%{range: %{field => %{gte: trunc(value - fuzz), lte: trunc(value + fuzz)}}}, r_tokens} + [{:literal_field, field}, {:eq, _}, {:text, value}, {:fuzz, _}, {:number, fuzz} | r_tokens] -> + {%{fuzzy: %{field => %{value: value, fuzziness: fuzz}}}, r_tokens} + [{:ngram_field, field}, {:eq, _}, {:text, value}, {:fuzz, _}, {:number, fuzz} | r_tokens] -> + {%{fuzzy: %{field => %{value: value, fuzziness: fuzz}}}, r_tokens} + [{:default, [text: value]}, {:fuzz, _}, {:number, fuzz} | r_tokens] -> + {%{fuzzy: %{default_field => %{value: value, fuzziness: fuzz}}}, r_tokens} + _ -> + search_range(ctx, tokens) + end end # - # Search terms + # Range queries # - defp search_term(_ctx, [{:term, _t} | rest]) do - {[], rest} + defp search_range(ctx, tokens) do + case tokens do + [{:int_field, field}, {range, _}, {:int, value} | r_tokens] when range in [:gt, :gte, :lt, :lte] -> + {%{range: %{field => %{range => value}}}, r_tokens} + [{:float_field, field}, {range, _}, {:float, value} | r_tokens] when range in [:gt, :gte, :lt, :lte] -> + {%{range: %{field => %{range => value}}}, r_tokens} + [{:date_field, field}, {range, _}, {:date, [lower, _higher]} | r_tokens] when range in [:gt, :gte, :lt, :lte] -> + {%{range: %{field => %{range => lower}}}, r_tokens} + _ -> + search_custom(ctx, tokens) + end end - defp search_term(_ctx, []), do: raise(ArgumentError, "Expected a term, got .") + defp search_custom(ctx, tokens) do + case tokens do + [{:custom_field, field}, {:text, value} | r_tokens] -> + {ctx[:field_transforms][field].(value), r_tokens} + _ -> + search_term(ctx, tokens) + end + end - defp search_term(_ctx, [{_, text} | _rest]), - do: raise(ArgumentError, "Expected a term, got `#{text}'.") + defp search_term(ctx, tokens) do + case tokens do + [{:date_field, field}, {:eq, _}, {:date, [lower, higher]} | r_tokens] -> + {%{range: %{field => %{gte: lower, lte: higher}}}, r_tokens} + [{:ngram_field, field}, {:eq, _}, {:text, value} | r_tokens] -> + {%{match: %{field => value}}, r_tokens} + [{_field_type, field}, {:eq, _}, {_value_type, value} | r_tokens] -> + {%{term: %{field => value}}, r_tokens} + [{:default, [text: value]} | r_tokens] -> + {%{term: %{ctx[:default_field] => value}}, r_tokens} + _ -> + raise ArgumentError, "Expected a term" + end + end end