I want to use elastic search to search through a large address database, and to make it like some other applications I start with the postcode first which is great to narrow down on the rest of the search query.
So with Search::Elasticsearch
I do
my $scroll = $e->scroll_helper(index => 'pdb', search_type => 'scan', size => 100,
body => {
query => {
bool => {
filter => [
{match => { pcode => $postcode }},
],
should => [
{match => { address => $keyword }},
{match => { name => $keyword }},
],
}
}
}
);
However that just spits out everything for $postcode
and regardless of what $keyword
is the result set is not further reduced.
I need to have $postcode
as a mandatory condition but also separately and in addition the other two fields to also be taken into account as a full text search.
How should I do this (Im looking at the docs and might be interpreting json->perl hashrefs wrong so any suggestions welcome)
For a hypothetical example:
User enters NW1 4AQ
, The above query will immediately return, say, Albany Street and Portland Street, if the user queries Portland
and that postcode, instead of getting both those results, I expect only Portland Street to be the result. Right now with the above It just keeps returning both entries.
Boolean, or a bool query in Elasticsearch, is a type of search that allows you to combine conditions using Boolean conditions. Elasticsearch will search the document in the specified index and return all the records matching the combination of Boolean clauses.
Using must_not tells Elasticsearch that document matches cannot include any of the queries that fall under the must_not clause. should – It would be ideal for the matching documents to include all of the queries in the should clause, but they do not have to be included. Scoring is used to rank the matches.
You can use two methods to filter search results: Use a boolean query with a filter clause. Search requests apply boolean filters to both search hits and aggregations. Use the search API's post_filter parameter.
Following common sense I found that the following does what I want for the bool
segment:
bool => {
must => [
{match => { pcode => $postcode }},
],
should => [
{match => { address => $keyword }},
{match => { name => $keyword }},
],
minimum_should_match => 1,
}
Having minimum_should_match
as 1 (which is a counter rather than true/false), feels like it's inserting an OR
in those should
s
Elastic doc says:
"By default, none of the should clauses are required to match, with one exception: if there are no must clauses, then at least one should clause must match. Just as we can control the precision of the match query, we can control how many should clauses need to match by using the
minimum_should_match
parameter, either as an absolute number or as a percentage"
So the way to do it is through minimum_should_match
. Just as you did. What you did means that either address or name must be matched.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With