I am attempting to use AEM's querybuilder API to do a generic search. The problem I am currently having is creating pagination with the querybuilder. While using the ResultPage class in AEM with SearchResult to getNextPage(). I am getting the result
com.day.cq.search.impl.result.ResultPageImpl#541bd4bf. How would I convert this into a URL? I already am using the offset and result total with the querybuilder but cannot find any more documentation to put me in the right direction.
queryBuilder=resource.getResourceResolver().adaptTo(QueryBuilder.class);
//creating query based on the Query Description
Query query=queryBuilder.createQuery(PredicateGroup.create(map),session);
//Getting and storing the Results
List Pages1 = searchRes.getResultPages();
ResultPage nextpage = searchRes.getNextPage();
ResultPage lastpage = searchRes.getPreviousPage();
for (Hit hit:searchRes.getHits()){
String path1=hit.getPath();
String title1=hit.getTitle();
String excerpt1=hit.getExcerpt();
You can't. The ResultPage objects have information about your search results that you got from the QueryBuilder. You can use the information to build your own pagination and search result page(s).
As the SearchResult object contains only the results from the current page, you can use the ResultPage to easily get index and start of all the other pages that you could request from the QueryBuilder, based on the settings you used for your query, for example:
query.setStart(start);
query.setHitsPerPage(hitsPerPage);
But there is no connection to the frontend...
Related
I want to enable search for a bunch of fields for one of my entities. Therefore, I added hibernate search to my spring boot project. When I load data into the database, I can see that Elasticsearch contains that data as expected in the index running
curl localhost:9200/myindex/_search?pretty
I can run queries like
curl localhost:9200/myindex/_search?pretty&q=name:test
and receive the expected results.
I would like to give consumers of my API the option to run arbitrary queries like "name:test" against the index, so that
curl "localhost:8086/myentity/search/querySearch?query=name:test"
would return the same results as before in the direct query.
Here's what I am trying but whatever I do, I get 0 results:
public List<MyEntity> querySearch(String queryString) {
QueryParser queryParser = new MultiFieldQueryParser(ALL_FIELDS, new SimpleAnalyzer());
queryParser.setDefaultOperator(QueryParser.AND_OPERATOR);
org.apache.lucene.search.Query query = queryParser.parse(QueryParser.escape(queryString));
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(this.entityManager);
javax.persistence.Query persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, MyEntity.class);
return persistenceQuery.getResultList();
}
By calling QueryParser.escape(queryString), you remove the meaning of operators such as :. So if the user enters name:test, you will end up looking for documents that contain name:test (literally), instead of looking for documents whose name field contains test.
Remove that escape and everything should work as you want.
By the way, you're essentially using Lucene to parse a query that will then be sent to Elasticsearch. An easier solution would be to send the query to Elasticsearch directly, especially if you do not need to prevent users from accessing some fields.
public List<Training> querySearch(String queryString) {
FullTextEntityManager fullTextEm = Search.getFullTextEntityManager(this.entityManager);
QueryDescriptor query = ElasticsearchQueries.fromQueryString(queryString);
javax.persistence.Query persistenceQuery = fullTextEm.createFullTextQuery(query, Training.class);
return persistenceQuery.getResultList();
}
See https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#_queries
I am attempting to count the number of documents of a specific type based on the value of 2 of the documents fields.
So far I can count the number of documents using:
SearchResponse response = elasticClient.getClient().prepareSearch(Properties.get().getSearch().getAliasName())
.setTypes(type)
.setSize(0) // Don't return any documents, we don't need them.
.get();
SearchHits hits = response.getHits();
return (int) hits.getTotalHits();
Which returns the correct number of total documents.
I can also search for a specific document using:
searchResponse = elasticClient.getClient()
.prepareSearch(index)
.setSearchType(SearchType.QUERY_THEN_FETCH)
.setQuery(QueryBuilders.prefixQuery(field_name, field_value))
.setFetchSource(true)
.setSize(10000)
.setTypes(type)
.addSort(builder.order(SortOrder.DESC))
.get();
This also returns documents.
I have attempted to count based on 2 field values using:
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must(QueryBuilders.prefixQuery(field_1, value_1));
queryBuilder.must(QueryBuilders.prefixQuery(field_2, value_2));
SearchRequestBuilder searchBuilder = elasticClient.getClient().prepareSearch(index)
.setQuery(queryBuilder)
.setTypes(type)
.setSize(0);
But this always returns 0.
How do I correctly count documents based on 2 field values using the Java API?
From inspecting the query, you are not passing both values together. You are first passing the query for field_1 and later overwriting it with the query for field_2. So the variable queryBuilder only has the query: QueryBuilders.prefixQuery(field_2, value_2) by the time you pass it to the client.
In elasticsearch query DSL, the must object is an array of queries that behave similar to an AND in a SQL where clause. So all the queries in the must list need to match. To include both queries in the must do the following:
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must().add(QueryBuilders.prefixQuery(field_1, value_1));
queryBuilder.must().add(QueryBuilders.prefixQuery(field_2, value_2));
As for the count, size = 0 should do the trick. What kind of elasticsearch client are you using?
Hi I am trying to do query on elastic search by following the sql query and I want to implement same logic using Java API
select * from log , web where l.loghost = w.webhost and #datetime between '2016-05-20' AND '2016-05-25'
log and web are different types, and indices are set to logstash-log-* and logstash-web*, #timestamp format looks like "2016-05-20T17:14:01.037Z"
Now I have the following Java code but i don't know how to set between two dates ,so it does not return expected output
SearchResponse response = client.prepareSearch("logstash-log-*","logstash-web-*")
.setTypes("log","web")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setFetchSource(new String[]{"*"}, null)
.setQuery(QueryBuilders.queryStringQuery("1.2.3.4").field("*_host"))// Query
.execute()
.actionGet();
Please guide I am new to Elastic search. Thanks in advance.
You need to combine a range query with your query_string query inside a bool/filter query:
QueryStringQueryBuilder qs = QueryBuilders.queryStringQuery("1.2.3.4").field("*_host");
RangeQueryBuilder range = QueryBuilders.rangeQuery("#timestamp")
.gte("2016-05-20T00:00:00.000Z")
.lte("2016-05-25T00:00:00.000Z");
and then
...
.setQuery(QueryBuilders.boolQuery().filter(qs).filter(range))
...
Is it possible not just sort results of query(com.google.appengine.api.search.Query), but also filter them? Like for example in this query com.google.appengine.api.datastore.Query:
Filter heightMinFilter =
new FilterPredicate("height",
FilterOperator.GREATER_THAN_OR_EQUAL,
minHeight);
Query q = new Query("Person").setFilter(heightMinFilter);
Search query has options that are needed for sorting, but I also want to filter result, because there are too many of them and I need only specific.
The filter is part of the query string.
A query string specifies conditions for the values of one or more
document fields. When you search an index you get back only those
documents in the index with fields that satisfy the query.
See example below or find more details here.
String queryString = "product: piano AND price < 5000";
Query query = Query.newBuilder().build(queryString);
Results<ScoredDocument> results = getIndex().search(queryString);
I'm new to Elasticsearch and tried to query some sample documents. I issued the following query using the Java API. This query fetched me the correct result. It returned the names of all categories. Now I want the count of all names of a category. Could you explain me how to do that? I'm sorry for my bad English.
SearchResponse sr = client.prepareSearch()
.addField("Category")
.setQuery(QueryBuilders.matchAllQuery())
.addFacet(FacetBuilders.termsFacet("f")
.field("Category"))
.execute()
.actionGet();
Look at the Count API to count your results if you not want to get the result set (matched documents) but only the count.
If you want to get the result set, you get the result size in the response for every filter or query request too.