From 2d762e9645b9f91460c2b0b202aacc740b7c6514 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Wed, 27 Nov 2019 00:09:46 -0500 Subject: [PATCH] flatten long chains of conjoined/disjoined terms and double negation --- lib/search/parser.ex | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/search/parser.ex b/lib/search/parser.ex index 7ba5c88d..aef60d8d 100644 --- a/lib/search/parser.ex +++ b/lib/search/parser.ex @@ -88,7 +88,7 @@ defmodule Search.Parser do with {:ok, {left, [{:or, _} | r_tokens]}} <- search_and(parser, tokens), {:ok, {right, rest}} <- search_or(parser, r_tokens) do - {:ok, {%{bool: %{should: [left, right]}}, rest}} + {:ok, {flatten_disjunction_child(left, right), rest}} else value -> value @@ -99,7 +99,7 @@ defmodule Search.Parser do with {:ok, {left, [{:and, _} | r_tokens]}} <- search_boost(parser, tokens), {:ok, {right, rest}} <- search_and(parser, r_tokens) do - {:ok, {%{bool: %{must: [left, right]}}, rest}} + {:ok, {flatten_conjunction_child(left, right), rest}} else value -> value @@ -119,7 +119,7 @@ defmodule Search.Parser do defp search_not(parser, [{:not, _} | rest]) do case search_group(parser, rest) do {:ok, {child, r_tokens}} -> - {:ok, {%{bool: %{must_not: child}}, r_tokens}} + {:ok, {flatten_negation_child(child), r_tokens}} value -> value @@ -271,4 +271,21 @@ defmodule Search.Parser do |> String.trim() |> String.downcase() end + + # Flattens the child of a disjunction or conjunction to improve performance. + defp flatten_disjunction_child(this_child, %{bool: %{should: next_child}}), + do: %{bool: %{should: [this_child | next_child]}} + defp flatten_disjunction_child(this_child, next_child), + do: %{bool: %{should: [this_child, next_child]}} + + defp flatten_conjunction_child(this_child, %{bool: %{must: next_child}}), + do: %{bool: %{must: [this_child | next_child]}} + defp flatten_conjunction_child(this_child, next_child), + do: %{bool: %{must: [this_child, next_child]}} + + # Flattens the child of a negation to eliminate double negation. + defp flatten_negation_child(%{bool: %{must_not: next_child}}), + do: next_child + defp flatten_negation_child(next_child), + do: %{bool: %{must_not: next_child}} end \ No newline at end of file