How to AND multiple setQuery in elasticsearch using java? - java

I am trying to create query for search filter using elasticsearch. I created query that shows results based on search term, price range and brand list. Results shown for searchterm and price range is right but when brand list is provided all results related to selected brand is shown.
I want results for searchterm AND price AND brands
This is my query
BoolQueryBuilder query = QueryBuilders.boolQuery();
for (String key : brands) {
query.must(QueryBuilders.matchQuery("brand", key));
}
SearchResponse searchresponse = client
.prepareSearch("product")
.setTypes("product")
.setQuery(
QueryBuilders.matchPhraseQuery("name", pSearchTerm))
.setPostFilter(
QueryBuilders.rangeQuery("unit_price").from(min)
.to(max))
.setQuery(query).setExplain(true)
.execute().actionGet();
what am i doing wrong here?

You have two setQuery() calls so the second one is overriding the first one. You need to combine all your constraints into one query like this:
// brand list
BoolQueryBuilder query = QueryBuilders.boolQuery();
for (String key : brands) {
query.must(QueryBuilders.matchQuery("brand", key));
}
// search term
query.must(QueryBuilders.matchPhraseQuery("name", pSearchTerm));
// price range
query.filter(QueryBuilders.rangeQuery("unit_price").from(min).to(max));
SearchResponse searchresponse = client
.prepareSearch("product")
.setTypes("product")
.setQuery(query)
.setExplain(true)
.execute().actionGet();

Related

Fetch all record including particular fields

I am working with Elasticcsearch 7.3. I want to fetch only two records of all the documents using JAVA Api from my index. I am using the following code but it returning the null object.
RestHighLevelClient client;
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.fetchSource("recipe_ID,recipe_url", null);
sourceBuilder.from(0);
SearchRequest searchRequest = new SearchRequest("recipes");
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHit searchHit = searchResponse.getHits().getAt(0);
String resultString = searchHit.getSourceAsString();
return resultString;
I need to include only two fields recipe_ID and recipe_url in my result.
You're on the right path, although source filtering requires you to specify your fields in an array like this:
String[] includeFields = new String[] {"recipe_ID", "recipe_url"};
sourceBuilder.fetchSource(includeFields, null);

Search and filter with Spring Data Elasticsearch

I have a JPA entity called Invoice with some properties and want to search and filter the results, but the filter is not working properly. I tried various combinations but no one worked for me.
This one correctly searches for instances having "foobar" in some of the properties:
// this is the search string...
String search = "foobar*";
QueryBuilder queryStringQuery = QueryBuilders.queryStringQuery(search);
NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder();
searchQuery.withQuery(queryStringQuery);
// build and run against the ElasticsearchRepository
NativeSearchQuery query = searchQuery.build();
Page<T> result = searchRepository.search(query);
This is working and gives me all invoices, but now I only want to have "new invoices", which is given by a property called "state", which then has the value "New".
Currently, last one I tried is this one (according to similar questions on SO):
String search = "foobar*";
QueryBuilder queryStringQuery = QueryBuilders.queryStringQuery(search);
NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder();
searchQuery.withQuery(queryStringQuery);
// add filter
QueryBuilder filters = QueryBuilders.termQuery("state", "New");
searchQuery.withFilter(searchFilters);
// build and run against the ElasticsearchRepository
NativeSearchQuery query = searchQuery.build();
Page<T> result = searchRepository.search(query);
This one gives me an empty result, although there must be some results.
I also tried to create somthing like this, but this is also not working:
String search = "foobar*";
QueryBuilder queryStringQuery = QueryBuilders.queryStringQuery(search);
searchFilters = QueryBuilders.termQuery("state", "New");
BoolQueryBuilder searchQuery = QueryBuilders.boolQuery().should(queryStringQuery).must(searchFilters);
Iterable<T> result = searchRepository.search(searchQuery);
Use something like this
QueryBuilder qb;
QueryBuilder stateFilters = QueryBuilders.boolQuery();
((BoolQueryBuilder) filters).filter(QueryBuilders.matchQuery("state", "New"));
qb = QueryBuilders.boolQuery().should(QueryBuilders.queryStringQuery("foobar*")).filter(stateFilters );
the filter function here helps us with this
here qb will have the proper query which can now be used to search using the elasticsearchRepository.search(qb);
Here is some information from spring docs:
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.operations

how can i do this query on dynamoDB + Android

I've got a DynamoDB table containing 'n' Book title in only one dynamoDB Item (and this freak me out)
in this structure, rentBook is the table on dynamoDB, with 2 attributes:
String StudentID
StringSet BookTitle // something like:["title1","title2","title3"]
In SQL I would have write something like that
SELECT StudentID
FROM RentBook
WHERE BookTitle = "title1" OR BookTitle = "title2"
but with Dynamo i can't get the right results :(
anyone can help me?
question 2: Is this table structure appropriate when the number of rows increases?
Try this:
ValueMap vm = new ValueMap().withString(":val1", "title1");
ScanRequest scanRequest = new ScanRequest()
.withTableName("RentBook")
.withFilterExpression("contains(BookTitle, :val1)")
.withExpressionAttributeValues(vm);

How build dynamic query elasticsearch

I would like to build a query to elasticsearch using search criteria from a html form. I have several input fields on the html page. For example, if the user fill two of these fields I could write :
BoolQueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("archivo", "archivo1"))
.must(QueryBuilders.termQuery("nombre", "documento1"));
But... what if the user fill three fields I could have :
BoolQueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("archivo", "archivo1"))
.must(QueryBuilders.termQuery("nombre", "documento1"))
.must(QueryBuilders.termQuery("third", "test"));
Is there any way to dinamicall build this kind of queries?
BoolQueryBuilder.must() adds a predicate, it does not replace the previous one.
Therefore, suppose that the value of the field archivo is in the variable inputArchivo and so on, you can check if the field is filled then add the predicate :
BoolQueryBuilder query = QueryBuilders.boolQuery();
if(inputArchivo != null && !inputArchivo.isEmpty()) {
query.must(QueryBuilders.termQuery("archivo", inputArchivo));
}
if(inputNombre != null && !inputNombre.isEmpty()) {
query.must(QueryBuilders.termQuery("nombre", inputNombre));
}
if(inputThird != null && !inputThird.isEmpty()) {
query.must(QueryBuilders.termQuery("third", inputThird));
}
and yet if you don't know what terms will came you can iterate over a HashMap with the values:
for (Map.Entry<String, Object> entry : map.entrySet()) {
query.must(QueryBuilders.termQuery(entry.getKey, entry.getValue))
}

elasticsearch QueryBuilder with dynamic list value in term query

I have a code like below where I'm doing multiple must in bool query. Here I'm passing the must term queries in field "address". Now the ip address will come to me as a list from other api and I have to pass for all the ip's in the list as a must term query. Here I'm not getting a way how to pass the address values dynamically when creating the QueryBuilder.
Please suggest how to do this.
public static SearchResponse searchResultWithAggregation(String es_index,
String es_type, List<String> ipList, String queryRangeTime) {
Client client = ESClientFactory.getInstance();
QueryBuilder qb = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("address", "10.203.238.138"))
.must(QueryBuilders.termQuery("address", "10.203.238.137"))
.must(QueryBuilders.termQuery("address", "10.203.238.136"))
.mustNot(QueryBuilders.termQuery("address", "10.203.238.140"))
.should(QueryBuilders.termQuery("client", ""));
queryRangeTime = "now-" + queryRangeTime + "m";
FilterBuilder fb = FilterBuilders.rangeFilter("#timestamp")
.from(queryRangeTime).to("now");
SearchResponse response = client
.prepareSearch(es_index)
.setTypes(es_type)
.setQuery(qb)
.setPostFilter(fb)
.addAggregation(
AggregationBuilders.avg("cpu_average").field("value"))
.setSize(10).execute().actionGet();
System.out.println(response.toString());
return response;
}
You can use the terms query to pass multiple values for single field.
create a string array or set. and pass it to the terms query.
Set<String> address = new HashSet<String>();
address.add("10.203.238.138");
address.add("10.203.238.137");
address.add("10.203.238.136");
if(address!=null)
QueryBuilder qb = QueryBuilders.boolQuery()
.must(QueryBuilders.termsQuery("address",address))
.mustNot(QueryBuilders.termQuery("address", "10.203.238.140"))
.should(QueryBuilders.termQuery("client", ""));
else
QueryBuilder qb = QueryBuilders.boolQuery()
.mustNot(QueryBuilders.termQuery("address", "10.203.238.140"))
.should(QueryBuilders.termQuery("client", ""));
Hope it helps..!
If you use TermsQuery for address array/set, it will return any documents that match with at least one or more of the provided terms.
List<String> address = new ArrayList<String>();
address.add("10.203.238.138");
address.add("10.203.238.137");
address.add("10.203.238.136");
BoolQueryBuilder qb = QueryBuilders.boolQuery();
qb.mustNot(QueryBuilders.termQuery("address", "10.203.238.140"));
qb.should(QueryBuilders.termQuery("client", ""));
for(String add: Address){
qb.must(QueryBuilders.termsQuery("address",add));
}

Categories

Resources