How to use QueryStringQueryBuilder - java

I've tried to use QueryStringQueryBuilder in a very simple case, but I dont understand why I get another result than the result I get from Kibana. What am I doing wrong?
Kibana:
GET .../_search
{
"query": {
"query_string" : {
"query" : "\"this is a query\"",
"lenient": true,
"default_operator": "OR"
}
}
}
Java:
private Optional<QueryStringQueryBuilder> parseQuery(String query) {
if (query.equals("")) {
return Optional.empty();
}
QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(query);
queryBuilder.lenient(true);
queryBuilder.defaultOperator(Operator.OR);
return Optional.of(queryBuilder);
}
Result from kibana: totalhits = 3336. Result from Java: totalhits = 10018.
EDIT:
This method calls parseQuery. Input is "this is a query".
public Optional<SearchRequestBuilder> getRequestBuilderByQuery(SearchQuery query) {
SearchRequestBuilder builder = getBuilderWithMaxHits(query.getMaxHits());
builder.setFetchSource(Globals.getFIELDS(query.isIncludeStory()), new String[0]);
parseQuery(query.getQuery()).ifPresent(builder::setQuery);
return Optional.of(builder);
}

I dont know what your input parameter 'query' in this case contains.
But i think you want to set queryBuilder.queryName(String queryName) in your QueryStringQueryBuilder.
From the JavaDocs:
queryName(String queryName):
Sets the query name for the filter that can be used when searching for matched_filters per hit.

Ok, I found the problem.
The query for kibana had quotation marks. Which meant it was processed differently than just a normal String. QueryStringQuerybuilder seems to be parsing the query by itself with "",AND,OR,NOT. This is magic!

Related

Elasticsearch wildcard query in Java - find all matching fields and replace

I want to update all path fields starting with "example/one".
Map<String, Object> parameters = new HashMap<>();
parameters.put("old", "example/one");
parameters.put("new", "new/example");
UpdateByQueryRequest request = new UpdateByQueryRequest(index)
.setDocTypes(type)
.setScript(new Script(ScriptType.INLINE,
"painless",
"ctx._source.path = ctx._source.path.replace(params.old, params.new);",
parameters))
.setQuery(QueryBuilders.wildcardQuery("path.tree", "example/one*"));
client.updateByQuery(request, RequestOptions.DEFAULT);
It's not working (no update, no errors - tried a prefixQuery, same). The following query however is updating the matching documents (Postman).
POST my_index/_update_by_query
{
"script": {
"lang": "painless",
"inline": "ctx._source.path = ctx._source.path.replace(\"example/one\", \"new/example\")"
},
"query": {
"wildcard": {
"path.tree": {
"value: "example/one*",
"boost": 1.0,
"rewrite": "constant_score"
}
}
}
}
What am I missing? The Path hierarchy tokenizer is used on the field path.
Your help is much needed.
PS: I can't upgrade to a newer version of elasticsearch.
When testing the solution, I first thought it was related to the custom analyser used on the path field. But it was quickly discarded as I was getting the expected result via Postman.
I finally decided to go with a 'two steps' solution (couldn't use the update by query API). First search for all matching documents, then perform a bulk update.
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.wildcardQuery("path.tree", "example/one*"))
.withSourceFilter(new FetchSourceFilter(new String[]{"_id", "path"}, null))
.build();
List<MyClass> result = elasticsearchRestTemplate.queryForList(query, MyClass.class);
if(!CollectionUtils.isEmpty(result)) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("old", "example/one");
parameters.put("new", "new/example");
Script script = new Script(ScriptType.INLINE,
"painless",
"ctx._source.path = ctx._source.path.replace(params.old, params.new)",
parameters);
BulkRequest request = new BulkRequest();
for (MyClass myClass : result) {
request.add(new UpdateRequest(index, type, myClass.getId()).script(script));
}
client.bulk(request, RequestOptions.DEFAULT);
}
UPDATE
Turns out setting the type in the request was the problem.
UpdateByQueryRequest request = new UpdateByQueryRequest(index)
.setDocTypes(type) <--------------- Remove
.....

Elasticsearch filter result ignoring search keyword

I am getting good result with normal search query.
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
String keyword = requestBody.getKeyword();
queryBuilder.should(QueryBuilders.matchQuery("fullText", keyword));
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.from(requestBody.getPage() - 1);
searchSourceBuilder.size(BROWSE_PAGE_DATA_LIMIT);
searchRequest.source(searchSourceBuilder);
try {
return client.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "Error in ES search");
}
But when I add filtering with it, the result is ignoring my search keyword.
queryBuilder.filter(QueryBuilders.termsQuery("authorId", filter.getAuthorIds()));
here I am trying to replace fq of solr. What's wrong at my approach.
Excerpt from ES Docs
If the bool query includes at least one should clause and no must or
filter clauses, the default value is 1. Otherwise, the default value
is 0.
Basically, if there is a filter or/and must clause with-in a bool query then the should clause is ignored until min_should_match is set to a suitable value.
Set minShouldMatch to 1. e.g:
queryBuilder.should(QueryBuilders.matchQuery("fullText", keyword)).minimumShouldMatch(1);

Hibernate OGM result of aggregation query

I am using hibernate ogm 5.1 in my application and I construct this query. This query
String query = "db.SWMessages.aggregate( [ {0}, {1} ] )";
Document q1 = new Document("$match",new Document("messageUuid",new
Document("$ne" , id.toString())));
Document q2 = new Document("$group", new Document("_id",
"$localReference").append("max", new Document("$max","$creationDate")));
Object[] param = { q1.toJson(), q2.toJson() };
String nativeQuery = MessageFormat.format(query, param);
List<SWMessageR> records = (List<SWMessageR>) em.createNativeQuery(nativeQuery, SWMessageImpl.class)
.getResultList();
the above code produces the query like this:
db.SWMessages.aggregate([ { "$match" : { "messageUuid" : { "$ne" : "9c1464d7-311d-4b50-8b81-005bad055232" } } } , { "$group" : { "_id" : "$localReference", "max" : { "$max" : "$creationDate" } } } ])
My question is that the result of this query would return back an entity object which is the SWMessageR?
Well, yes the way you execute your query it will return a List Object of your class. In this way you don't need to use casting, so you can use it like this:
List<SWMessageR> records = em.createNativeQuery(nativeQuery, SWMessageImpl.class).getResultList();
Though, in case you are expecting a single result, I would suggest to use this way:
SWMessageR record = (SWMessageR) em.createNativeQuery( query1, SWMessageR.class ).getSingleResult();
Have a look at the Hibernate Search Documentation Query Section and everything will be clear.
Cheers.
Hibernate OGM can convert the result into an entity: https://docs.jboss.org/hibernate/stable/ogm/reference/en-US/html_single/#ogm-mongodb-queries-native
I'm not sure what your query returns, but if it's a document in the collection that represents your entity, I expect it to work.
You can see an example in our code base:
https://github.com/hibernate/hibernate-ogm/blob/master/mongodb/src/test/java/org/hibernate/ogm/datastore/mongodb/test/query/nativequery/MongoDBSessionCLIQueryTest.java#L111
Make sure to pass the expected Entity type, it will look something like this:
List<SWMessageR> results = em
.createNativeQuery( nativeQuery, SWMessageR.class )
.getResultList();
Assuming that SWMessageR is the entity class.

How to represent the following query(mongodb) in java

I have a JSON in MongoDB with the following structure:
{
id:"_234234",
"stationId":"ALM",
"storageData": {
}
}
To retrieve JSON with storageData equal to null, in MongoDB I query as:
db.collection.find({"storageData":{"$gt" : {}}})
It gives me list of JSON bodies with empty storageData. So how do I represent that in Java
BasicDBObject obj=new BasicDDBObject("storageData", new BasicDBObject("$gt",{}));
collection.find(obj);
I am getting an error near BasicDBObject("$gt",{}))...
How do I represent ("$gt",{}) in Java??
First understand that null is a valid value. This would be valid:
{
id:"_234234",
StationId:"ALM",
StorageData: null
}
and retrieving the document, asking for storagedata which is null would retrieve the doc with the id _234234.
If what you need is to check which documents DON'T have the key "storagedata" then use the $exist keyword or construct the query in this way:
db.yourcollection.find("this.storagedata == null")
I would do it via query, and not in Java because it would alleviate cpu time and memory.
All you want to to here is represent an empty object:
BasicDBObject query = new BasicDBObject(
"storageData", new BasicDBObject(
"$gt",new BasicDBObject()
)
);
Which of course produces the query:
{ "storageData" : { "$gt" : { } } }
So that's it, just call BasicDBObject without any arguments.

Query Elasticsearch using String in java

I am using Elasticsearch maven jar file to query Elasticsearch. But now I want to query the elasticsearch using full generated query string:
query :
{
"bool" : {
"must" : [ {
"term" : {
"title" : "mercedes"
}
}, {
"term" : {
"Doors" : "2"
}
} ]
}
}
How do I use the above query string to query elasticsearch in java?
Following code prepares a boolquery. You should create a SearchRequestBuilder to execute it.
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
boolQuery.must(QueryBuilders.termQuery("title", "mercedes"));
boolQuery.must(QueryBuilders.termQuery("Doors", "2"));
If you want to use query as string without building it in code, you can use following;
String myQuery = "Your Query Here";
SearchSourceBuilder ssb= new SearchSourceBuilder();
search.query(myQuery);
SearchRequestBuilder srb; // You should define srb before next steps
srb.internalBuilder(ssb);
SearchResponse response = srb.execute().actionGet();
I use the following code to query Elasticsearch using JSON string.
SearchResponse response = client.prepareSearch(yourIndexName)
.setSource(yourJsonQueryString)
.execute().actionGet();

Categories

Resources