AshScylla.Search.Query.BooleanEngine (AshScylla v1.9.0)

Copy Markdown View Source

Boolean operations on posting lists.

Implements efficient set operations using a two-pointer merge algorithm with O(n + m) complexity — identical to how Lucene performs intersections and unions.

Supports:

  • AND — intersection of posting lists
  • OR — union of posting lists
  • NOT — difference of posting lists

Summary

Functions

Computes the AND intersection of multiple posting lists.

Computes the AND intersection of multiple scored posting lists ({post_id, tf} pairs sorted by post_id).

Computes the difference: posts in include that are NOT in exclude.

Computes the OR union of multiple posting lists.

Computes the OR union of multiple scored posting lists ({post_id, tf} pairs). Scores of posts appearing in several lists are summed. The result is sorted by post_id.

Types

posting_list()

@type posting_list() :: [{String.t(), non_neg_integer(), non_neg_integer()}]

scored_list()

@type scored_list() :: [scored_post()]

scored_post()

@type scored_post() :: {String.t(), non_neg_integer()}

Functions

and_intersect(lists)

@spec and_intersect([posting_list()]) :: scored_list()

Computes the AND intersection of multiple posting lists.

Uses a two-pointer merge algorithm for each pair of lists.

Example

iex> BooleanEngine.and_intersect([
...>   [{"a", 1, 0}, {"b", 1, 1}, {"c", 1, 2}],
...>   [{"b", 1, 0}, {"c", 1, 1}, {"d", 1, 2}]
...> ])
[{"b", 1}, {"c", 3}]

intersect_scored(list)

@spec intersect_scored([scored_list()]) :: scored_list()

Computes the AND intersection of multiple scored posting lists ({post_id, tf} pairs sorted by post_id).

Uses a two-pointer merge algorithm for each pair of lists, summing the scores of matching posts.

Example

iex> BooleanEngine.intersect_scored([
...>   [{"a", 2}, {"b", 1}, {"c", 3}],
...>   [{"b", 4}, {"c", 1}, {"d", 2}]
...> ])
[{"b", 5}, {"c", 4}]

not_difference(include, exclude)

@spec not_difference(posting_list(), posting_list()) :: [
  {String.t(), non_neg_integer()}
]

Computes the difference: posts in include that are NOT in exclude.

Example

iex> BooleanEngine.not_difference(
...>   [{"a", 1, 0}, {"b", 1, 1}, {"c", 1, 2}],
...>   [{"b", 1, 0}]
...> )
[{"a", 1}, {"c", 1}]

or_union(lists)

@spec or_union([posting_list()]) :: scored_list()

Computes the OR union of multiple posting lists.

Example

iex> BooleanEngine.or_union([
...>   [{"a", 1, 0}, {"b", 1, 1}],
...>   [{"b", 1, 0}, {"c", 1, 1}]
...> ])
[{"a", 1}, {"b", 1}, {"c", 1}]

union_scored(lists)

@spec union_scored([scored_list()]) :: scored_list()

Computes the OR union of multiple scored posting lists ({post_id, tf} pairs). Scores of posts appearing in several lists are summed. The result is sorted by post_id.

Example

iex> BooleanEngine.union_scored([
...>   [{"a", 1}, {"b", 2}],
...>   [{"b", 4}, {"c", 1}]
...> ])
[{"a", 1}, {"b", 6}, {"c", 1}]