Elasticsearch query through Java API - java

I am using the following elasticsearch query to fetch the details,
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"bool": {
"should": [
{"match": {
"val": "GET"
}}]
}
}
}
}
}
It is working fine and given the result as required.
I want to execute the same query through java and get the same results and tried the following,
getClient().prepareSearch(esIndex)
.setQuery(QueryBuilders.queryStringQuery(QUERY)).execute().actionGet();
It is not returning the data and throw some query format wrong exception as well.
Is there any Java API available using which the same query can be executed?
NOTE: There is a possibility available to create the boolquery and aggregation builders in java api and execute the same. I am just curious to find a way to execute this query directly through elasticsearch java api

If you really want to use the Query String Query, your query has to follow Query String Syntax:
getClient().prepareSearch(esIndex)
.setQuery(QueryBuilders.queryStringQuery("val: \"GET\""))
.execute()
.actionGet();
As already stated, you should construct your query by using the provided QueryBuilders instead of strings. This will keep your code clean and readable even for complex queries.
getClient().prepareSearch(esIndex)
.setQuery(QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("val", "GET"))
.execute()
.actionGet();

BoolQueryBuilder bool = boolQuery();
bool.must(QueryBuilders.matchAllQuery());
bool.filter(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("Val", "GET")));
AggregationBuilder agg = AggregationBuilders.terms("").field("");
SearchResponse reponse = getClient().prepareSearch().setIndices("indexName").setTypes("indexType")
.setQuery(bool).addAggregation(agg).execute().actionGet();

you should use boolQuery() when you construct your QueryBuilder:
QueryBuilder qb = boolQuery()
.must(termQuery("content", "test1"))
.must(termQuery("content", "test4"))
.mustNot(termQuery("content", "test2"))
.should(termQuery("content", "test3"))
.filter(termQuery("content", "test5"));
Official docs:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-compound-queries.html

Related

Using queryStringQuery and boolQuery for date range

I am using Java to run queries on ElasticSearch. I'm having difficulties running range queries using boolQuery() API and queryStringQuery as input. here's the code:
QueryBuilder stringQuery = QueryBuilders.queryStringQuery(query);
QueryBuilder finalQuery = QueryBuilders.boolQuery().should(stringQuery);
The data field for date has the following format:
"startedOn" : { "type" : "date", "format": "yyyy-MM-dd HH:mm:ss.SSSSSS" }
and I am using queries like these:
StartedOn < 2020-06-29
StartedOn : [2020-06-20 TO 2020-06-25]
But none of them seem to return the correct results. Am I missing something here?
Thanks.

Issue with converting ES query to sort nested objects by key and value to Java API (ES version 6.2)

I would like to convert the below ES query to Java API
{
"sort": [
{
"nested_objects.Value": {
"order": "desc",
"nested_path": "nested_objects",
"nested_filter": {
"term": { "nested_objects.Key": "abc" }
}
}
}
]
}
Tried to write a query as below but looks like the previously working methods are now deprecated in ES 6.2
FieldSortBuilder mySort = SortBuilders.fieldSort("nested_objects.Value")
.setNestedFilter(QueryBuilders.nestedQuery("nested_objects",
QueryBuilders.termQuery("nested_objects.Key", "abc"), ScoreMode.Avg))
.order(SortOrder.DESC);
setNestedFilter() appears to be deprecated any alternatives?
I've copied the below text from this Deprecated List Link
org.elasticsearch.search.sort.FieldSortBuilder.getNestedFilter()
set nested sort with FieldSortBuilder.setNestedSort(NestedSortBuilder) and retrieve with FieldSortBuilder.getNestedSort()
org.elasticsearch.search.sort.FieldSortBuilder.getNestedPath()
set nested sort with FieldSortBuilder.setNestedSort(NestedSortBuilder) and retrieve with FieldSortBuilder.getNestedSort()
You can see how they mentioned that you would need to make use of NestedSortBuilder
Below is what you can do. Simply create a Term Query using QueryBuilder and make use of it in setFilter method chaining to setNestedSort.
QueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("nested_objects.Key", "abc"));
FieldSortBuilder mySort = SortBuilders.fieldSort("nested_objects.Value")
.order(SortOrder.DESC)
.setNestedSort(new NestedSortBuilder("nested_objects")
.setFilter(query));
Hope it helps!

elasticsearch query on comparing 2 fields (using java)

I've an index in my elasticsearch and I want to have a query to compare 2 date fields.
assuming fields name are creationDate and modifiedDate. I want to get all documents which these 2 dates are the same in them.
I know it was possible to use FilteredQuery which is deprecated right now.
something like the bellowing code:
FilteredQueryBuilder query = QueryBuilders.filteredQuery(null,
FilterBuilders.scriptFilter("doc['creationDate'].value = doc['modifiedDate'].value"));
Also it's maybe possible to write manual scripts as string, but I doubt that this is the right solution. Any idea's to create the properly query would be appreciated.
Filtered query have been replaced by bool/filter queries You can do it like this:
BoolQueryBuilder bqb = QueryBuilders.boolQuery()
filter(QueryBuilders.scriptQuery("doc['creationDate'].value = doc['modifiedDate'].value"));
However, instead of using scripts at search time, you'd be better off creating a new field at indexing time that contains the information of whether creationDate and modifiedDate are the same dates. Then, you could simply check that flag at query time, it would be much more optimal and fast.
If you don't want to reindex all your data, you can update all of them with that flag, simply run an update by query like this:
POST my-index/_update_by_query
{
"script": {
"source": """
def creationDate = Instant.parse(ctx._source.creationDate);
def modifiedDate = Instant.parse(ctx._source.modifiedDate);
ctx._source.modified = ChronoUnit.MICROS.between(creationDate, modifiedDate) > 0;
""",
"lang": "painless"
},
"query": {
"match_all": {}
}
}
And then your query will simply be
BoolQueryBuilder bqb = QueryBuilders.boolQuery()
filter(QueryBuilders.termQuery("modified", "false");

Java (ElasticSearch) - build query due to the many fields

I use Java and Java High Level REST Client.
I need to build query that will find documents. This query should contain many fields for searching.
For example, I have such json:
{
"timeStamp": "Fri, 29 Dec 2017 15:32:22 +0000",
"value": 314,
"operation": "http://software-testing.ru/library/testing/testing-tools/2638-postman",
"type": "duration",
"system": "front-admin"
}
and I need find all document due to the all fields.
I understand how constract query due to the one field (parametr) but don't know how I can use a lot of fields for query:
#PostMapping("/findMetricsByValues") #Transactional public ResponseEntity findMetricsByValues(#RequestBody ElasticSearchMetrics metrics){
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termQuery("value", metrics.getValue()));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = client.search(searchRequest);
} catch (IOException e) {
e.printStackTrace();
}
return new ResponseEntity<>(new GenericResponse(searchResponse, CODE_200), HttpStatus.OK); }
Could somebody help with it or give a hint?
You can use QueryBuilders.queryStringQuery(String query) method instead
In this you can write query according to may fields
Below is a link that can help you with this ->
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-query-string-query.html
There are many clauses like AND , OR for joining multiple queries.
Here is syntax for writing query in a string -> https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-query-string-query.html#query-string-syntax
You can use bool query -> https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-bool-query.html

How to construct QueryBuilder from JSON DSL when using Java API in ElasticSearch?

I'm using ElasticSearch as a search service in Spring Web project which using Transport Client to communicate with ES.
I'm wondering if there exists a method which can construct a QueryBuilder from a JSON DSL. for example, convert this bool query DSL JSON to a QueryBuilder.
{
"query" : {
"bool" : {
"must" : { "match" : {"content" : "quick"},
"should": { "match": {"content" : "lazy"}
}
}
}
I need this method because I have to receive user's bool string input from web front-side, and parse this bool string to a QueryBuilder. However it not suit to use QueryBuilders.boolQuery().must(matchQB).should(shouldQB).must_not(mustNotQB). Because we may need several must or non must query.
If there exist a method can construct a QueryBuilder from JSON DSL or there exists alternative solutions, it will much easier.
PS: I have found two method which can wrap a DSL String to a QueryBuilder for ES search.
One is WrapperQueryBuilder, see details here. http://javadoc.kyubu.de/elasticsearch/HEAD/org/elasticsearch/index/query/WrapperQueryBuilder.html
Another is QueryBuilders.wrapperQuery(String DSL).
You can use QueryBuilders.wrapperQuery(jsonQueryString);
You can use setQuery, which can receive a json format string.
/**
* Constructs a new search source builder with a raw search query.
*/
public SearchRequestBuilder setQuery(String query) {
sourceBuilder().query(query);
return this;
}
Note this: only part of the DSL is needed, the {"query": } part is omitted, like this:
SearchResponse searchResponse = client.prepareSearch(indices).setQuery("{\"term\": {\"id\": 1}}").execute().actionGet();
It might be worth investigating low level rest client. With this you can do:
RestClient esClient = RestClient.builder(new HttpHost("localhost", 9200, "http")).build();
Request request = new Request("POST", "/INDEX_NAME/_doc/_search");
request.setJsonEntity(yourJsonQueryString);
Response response = esClient.performRequest(request);
String jsonResponse = EntityUtils.toString(response.getEntity());

Categories