package Elastic::Manual::QueryDSL;
# ABSTRACT: How to use the Elasticsearch Query DSL
__END__
=pod
=encoding UTF-8
=head1 NAME
Elastic::Manual::QueryDSL - How to use the Elasticsearch Query DSL
=head1 VERSION
version 0.52
=head1 INTRODUCTION
Elasticsearch provides a rich query language, known as the
L<Query DSL|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html> which
exposes much of the power of Lucene through a simple JSON interface.
It is tuned for full text search, but is in no way limited just
to that. It also provides very fast and flexible filters, ranges, geo-location
and more.
L<ElasticSearch::SearchBuilder> is a more concise, more Perlish version
of the Query DSL, similar to L<SQL::Abstract>. Both syntaxes are
fully supported by Elastic::Model.
In L<Elastic::Model::View>, L<query|Elastic::Model::View/query>,
L<filter|Elastic::Model::View/filter> and
L<post_filter|Elastic::Model::View/post_filter> expect the native
Query DSL, while L<queryb|Elastic::Model::View/queryb>,
L<filterb|Elastic::Model::View/filterb> and
L<post_filterb|Elastic::Model::View/post_filterb> (note the extra "b") expect
the SearchBuilder syntax.
=head1 FULL TEXT VS EXACT MATCHING
There are two broad ways to match values in ElasticSearch:
=head2 Exact matching
=over
=item *
Documents where C<< status eq 'active' >>
=item *
Documents with any of the tags C<"perl">, C<"python"> or C<"ruby">
=item *
Documents published between 2012-01-01 and 2012-12-31
=item *
Documents within 50km of geo-point Lat,Lon
=item *
Documents that have a value in the C<name> field
=back
=head2 Full text matching
=over
=item *
Documents which are relevant to the search terms "quick brown fox"
=item *
Documents about "Big Mac", but not about "Apple Mac"
=item *
Documents about "flying kites", where the text may include "fly", "flying",
"kite" or "kites"
=item *
The most relevant auto-complete terms which match the partial phrase
"arnold schwa"
=back
You can only find what is actually stored in Elasticsearch. For this reason,
exact matching is easy. Full text matching is B<made> easy by the analysis
process, which you can read more about in L<Elastic::Manual::Analysis>.
=head1 QUERIES VS FILTERS
Every search has a single query, but that query can contain multiple other
queries and filters. Choosing the right tool for the job is important:
=over
=item Filters:
=over
=item *
are for L</Exact matching> only
=item *
are boolean: a doc either matches or it doesn't. There is no scoring phase
=item *
are faster
=item *
are cacheable
=back
=item Queries:
=over
=item *
can be used for L</Exact matching> or for L</Full text matching>
=item *
score each document by "relevance" (see L<http://www.lucenetutorial.com/advanced-topics/scoring.html>
for a summary of how scoring works)
=item *
are slower, because of the scoring phase
=item *
are not cacheable
=back
=back
B<In summary>: you should use filters for any part of the query that does not
require relevance scoring.
B<Note:> a search for documents which have the exact tags C<"perl"> or C<"python">
may use a filter or a query. If all you care about is that each document
has at least one of those tags, then use a filter. If a document that has
BOTH tags should be considered more relevant than a document with only
one tag, then you need a query.
=head1 USING QUERIES AND FILTERS WITH ELASTIC::MODEL::VIEW
L<Elastic::Model::View> gives you a "view" across your data. It is the
class you use to build your searches.
Just a query:
$view->query( match => { title => 'object models' })->search;
Just a filter:
$view->filter( terms => { tags => ['perl','python' ] })->search
A query and filter combined:
$view->query( match => { title => 'object models' })
->filter( terms => { tags => ['perl','python' ] })->search
Or, with the SearchBuilder syntax:
$view->queryb( title => 'object models' )
->filterb( tags => ['perl','python' ] )->search
B<Note:> Elasticsearch only accepts a C<query> parameter, so the
L<query|Elastic::Model::View/query> and L<filter|Elastic::Model::View/filter>
attributes are combined at search time. This means that you can quite happily
specify queries with nested filters using just the
L<query|Elastic::Model::View/query> attribute.
B<Note:> the L<post_filter|Elastic::Model::View/post_filter> works in exactly
the same way as L<filter|Elastic::Model::View/filter>, but it only filters
the results AFTER the L<aggregations|Elastic::Model::View/aggs> (like GROUP BY)
have been calculated.
=head1 QUERIES
See L<Elastic::Manual::QueryDSL::Queries> for examples of commonly used queries.
=head1 FILTERS
See L<Elastic::Manual::QueryDSL::Filters> for examples of commonly used filters.
=head1 AUTHOR
Clinton Gormley <drtech@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2015 by Clinton Gormley.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut