![Build Status][build_status_svg]
A query builder for the AWS CloudSearch structured search syntax. This query builder is largely inspired by csquery for Python.
CSQuery
is a pure library, so it only needs to be added to your dependencies.
@deps [
csquery: "~> 1.0"
# OR: {:csquery, github: "KineticCafe/csquery"}
]
def deps: @deps
CSQuery
is a structured search syntax query builder for AWS CloudSearch. It
serves one purpose: build a structured query. It does not integrate with
any networking library. The queries built with this library are raw input to
the q
parameter of a CloudSearch request when q.parser=structured
.
It does not support, and will not support, other query parsers provided by AWS CloudSearch (simple, lucene, or dismax). Other libraries may be able to provide structured query building for those parsers.
CSQuery provides two ways of building a query:
-
A DSL-style approach like the Python implementation:
iex> and!([title: "star", actor: "Harrison Ford", boost: 2]) |> to_query() "(and boost=2 title:'star' actor:'Harrison Ford')"
-
A structured parser:
iex> parse(and: [title: "star", actor: "Harrison Ford", boost: 2]) |> ...> to_query() "(and boost=2 title:'star' actor:'Harrison Ford')"
The structured parser feels like it fits better in the style of Elixir,
especially with complex queries (see below). Both are supported (and are
implemented the same way). The documentation for each operator is on the
DSL-like functions below (as with and!/1
), but examples are given for both
forms.
A complex query can be built with sufficient nesting:
iex> and!([
...> not!(["test", field: "genres"]),
...> or!([
...> term!(["star", field: "title", boost: 2]),
...> term!(["star", field: "plot"])
...> ])
...> ]) |> to_query
"(and (not field=genres 'test') (or (term boost=2 field=title 'star') (term field=plot 'star')))"
iex> parse(and: [
...> not: ["test", field: "genres"],
...> or: [
...> term: ["star", field: "title", boost: 2],
...> term: ["star", field: "plot"]
...> ]
...> ]) |> to_query
"(and (not field=genres 'test') (or (term boost=2 field=title 'star') (term field=plot 'star')))"
It is also possible to mix and match the forms (but please avoid this):
iex> parse(and: [
...> not!(["test", field: "genres"]),
...> or: [
...> term: ["star", field: "title", boost: 2],
...> term: ["star", field: "plot"]
...> ]
...> ]) |> to_query
"(and (not field=genres 'test') (or (term boost=2 field=title 'star') (term field=plot 'star')))"
-
Strings:
iex> term!(["STRING"]) |> to_query "(term 'STRING')"
-
Ranges:
iex> range!([1..2]) |> to_query "(range [1,2])" iex> range!([{nil, 10}]) |> to_query "(range {,10])" iex> range!([{10, nil}]) |> to_query "(range [10,})" iex> range!([CSQuery.Range.new(%{first?: 0, last?: 101})]) |> to_query "(range {0,101})"
-
Numbers:
iex> term!([10]) |> to_query "(term 10)" iex> term!([3.14159]) |> to_query "(term 3.14159)"
-
DateTime (
t:DateTime.t/0
):iex> %DateTime{ ...> year: 2018, month: 7, day: 21, ...> hour: 17, minute: 55, second: 0, ...> time_zone: "America/Toronto", zone_abbr: "EST", ...> utc_offset: -14_400, std_offset: 0 ...> } |> List.wrap() |> term! |> to_query "(term '2018-07-21T17:55:00-04:00')"
-
Terms:
iex> or!(["(and 'star' 'wars')", "(and 'star' 'trek')"]) |> to_query "(or (and 'star' 'wars') (and 'star' 'trek'))"
The forthcoming ExAws.CloudSearch library will recognize CSQuery-generated expressions and configure its query request so that the structured parser is used.
We welcome your contributions, as described in Contributing.md. Like all Kinetic Cafe open source projects, is under the Kinetic Cafe Open Source Code of Conduct.