How to create a search with or clause using Elasticsearch - elasticsearch

I want to create a query with Elasticsearch Java API but I don't know how to create an OR clause? What I want to query is;
SELECT *
FROM USERS
WHERE (user.name = "admin") AND (user.message LIKE "test*") AND (user.age = "30" OR user.status = "major")
I have created a query like below but I don't know how to create an OR clause like sql query;
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("name", "admin"));
boolQueryBuilder.must(QueryBuilders.matchQuery("message", "test*"));
boolQueryBuilder.must(QueryBuilders.matchQuery("age", "30"));
boolQueryBuilder.must(QueryBuilders.matchQuery("status","major"));

You simply need to capture the OR condition inside another bool/should query
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("name", "admin"));
boolQueryBuilder.mustNot(QueryBuilders.matchQuery("message", "test*"));
BoolQueryBuilder orQuery = QueryBuilders.boolQuery();
orQuery.should(QueryBuilders.matchQuery("age", "30"));
orQuery.should(QueryBuilders.matchQuery("status","major"));
orQuery.minimumNumberShouldMatch(1);
boolQueryBuilder.must(orQuery);
PS: not sure why you have a mustNot for your second constraint.

The "should" keyword in bool queries works like "OR", but in Elasticsearch those queries are not very sharp as everything is scored.
Have a look at:
https://www.elastic.co/guide/en/elasticsearch/guide/current/bool-query.html#bool-query
Also there are very good examples in the book Elasticsearch in Action.

Related

How to search Exact string in elasticsearch DB

Search string in elastic search DB. Can any one please help to resolve this issue.
I am facing issue when I try using below snippet,
BoolQueryBuilder qb = QueryBuilders.boolQuery();
QueryBuilder qbm = QueryBuilders.matchQuery("Coloumname", "textValue");
Thanks.

Elasticsearch simultaneously search by two documents

I have two different documents in the Elasticsearch - Decision and Nomination.
Right now I can only search all of the documents wit Decision type.
I use Spring Data Elasticsearch for this purpose:
PageRequest pageRequest = DecisionUtils.createPageRequest(pageNumber, pageSize);
MultiMatchQueryBuilder fuzzyMmQueryBuilder = multiMatchQuery(query, "name", "description").fuzziness("AUTO");
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder().should(fuzzyMmQueryBuilder);
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withIndices(ESDecision.INDEX_NAME).withTypes(ESDecision.TYPE).withPageable(pageRequest);
NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.withQuery(boolQueryBuilder).withPageable(pageRequest).build();
return elasticsearchTemplate.queryForPage(nativeSearchQuery, ESDecision.class);
Is it possible to update this code to search by Decision and Nomination simultaneously in order to get the search result from both of them ? If the answer is yes - please show an example how to implement this and also please show how to determine at search results who is Decision and who is Nomination ? Is there any classification field that can be added into search result entity for this purpose ?

Elasticsearch - get source field data with java api

I'm using elastic search with jest (as java client).
I need some fields that is in nested document and since cannot get nested fields as pair, I need '_source' to get them.
Here is previous question to get them in ES query[ Link ], and It works well.
BUT cannot convert its query as jest code.
Below is my try.
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(
query
)
.fields( // need _source but no method.
"oid",
"_source.events.activityoid",
"_source.events.worktime");
Try using fetchSource() like this:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(query)
.fetchSource(new String[] {
"oid",
"events.activityoid",
"events.worktime"
}, null);

Elasticsearch should not operation query

Say we can match ("name"="A" AND "name!="B") as,
BoolQueryBuilder queryBuilder1 = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("name","A"))
.mustNot(QueryBuilders.matchQuery("name","B"));
How can I imply a "shouldNot" operation for ("name"="A" OR "name"!="B")
like,
BoolQueryBuilder queryBuilder1 = QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("name","A"))
.sholdNot(QueryBuilders.matchQuery("name","B")); // This API not exists..!
You can use this:
BoolQueryBuilder queryBuilder1 = QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("name","A"))
.should(QueryBuilders.boolQuery()
.mustNot(QueryBuilders.matchQuery("name","B")))

Filtered Query in Elasticsearch Java API

I am little bit confused while creating Filtered query in Elasticsearch Java API.
SearchRequestBuilder class has setPostFilter method, javadoc of this method clearly says that filter will be applied after Query is executed.
However, there is no setFilter method Or some other method which will allow to apply filter before
query is executed. How do I create filtered Query(which basically applies filter before query is executed) here? Am I missing something?
FilteredQueryBuilder builder =
QueryBuilders.filteredQuery(QueryBuilders.termQuery("test",
"test"),FilterBuilders.termFilter("test","test"));
It will build the filtered query...To filteredQuery, first argument is query and second arguments is Filter.
Update: Filtered query is depreciated in elasticsearch 2.0+.refer
Hope it helps..!
QueryBuilders.filteredQuery is deprecated in API v. 2.0.0 and later.
Instead, filters and queries have "equal rights". FilterBuilders no longer exists and all filters are built using QueryBuilders.
To implement the query with filter only (in this case, geo filter), you would now do:
QueryBuilder query = QueryBuilders.geoDistanceQuery("location")
.point(center.getLatitude(), center.getLongitude())
.distance(radius, DistanceUnit.METERS);
// and then...
SearchResponse resp = client.prepareSearch(index).setQuery(query);
If you want to query by two terms, you would need to use boolQuery with must:
QueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("user", "ben"))
.must(QueryBuilders.termQuery("rank", "mega"));
// and then...
SearchResponse resp = client.prepareSearch(index).setQuery(query);
In case you just want to execute filter without query, you can do like this:
FilteredQueryBuilder builder = QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(),
FilterBuilders.termFilter("username","stackoverflow"));
Ref: Filtering without a query
It seems that by wrapping the query (a BoolQueryBuilder object) by giving it as an argument to boolQuery().filter(..) and then setting that in the setQuery() as you suggested- then this can be achieved. The "score" key in the response is always 0 (though documents are found)
Be careful here! If the score is 0, the score has been calculated. That means the query is still in query context and not in filter context. In filter context the score is set to 1.0 (without calculation) source
To create a query in filter context without calculation of the score (score = 1.0) do the following (Maybe there is still a better way?):
QueryBuilder qb = QueryBuilders.constantScoreQuery(QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("name", "blub)));
This returns the same results like:
GET /indexName/typeName/_search
{
"filter": {
"query": {
"bool": {
"must": [
{ "match": {
"name": "blub"
}}
]
}
}
}
}
Since FilteredQueryBuilder is deprecated in the recent versions, one can use the QueryBuilders.boolQuery() instead, with a must clause for the query and a filter clause for the filter.
import static org.elasticsearch.index.query.QueryBuilders.*;
QueryBuilder builder = boolQuery().must(termQuery("test", "test")).filter( boolQuery().must(termQuery("test", "test")));

Resources