Set json string custom query to an elastic search request, java RestHighLevelClient - java

I'm using the RestHighLevelClient and I'm facing some trouble.
From front end, I will receive a json String like that:
{"query":{"term":{"something.keyword":"something"}}}
and I need to add that String to a SearchRequest or, better, create a SearchRequest from the json above
How can I do that without creating a parser and create programmatically the QueryBuilder to add to the searchRequest?
EDIT:
I've already tried the wrapper query, but executing this query:
{
"query": {
"wrapper": {
"query": "eyJxdWVyeSI6eyJ0ZXJtIjp7ImV2ZW50LmtpbmQua2V5d29yZCI6ImV2ZW50In19fSA="
}
}
}
I have this response:
{
"error" : {
"root_cause" : [
{
"type" : "parsing_exception",
"reason" : "unknown query [query]",
"line" : 1,
"col" : 10
}
],
"type" : "parsing_exception",
"reason" : "unknown query [query]",
"line" : 1,
"col" : 10,
"caused_by" : {
"type" : "named_object_not_found_exception",
"reason" : "[1:10] unknown field [query]"
}
},
"status" : 400
}
EDIT 2:
Sorry, the wrapper works just perfectly! I had to remove the "query" from the string, my fault.

As Val suggested, you can write the SearchRequest this way:
SearchRequest searchRequest = new SearchRequest("indexName");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.wrapperQuery("your json goes here"));
searchRequest.source(searchSourceBuilder);

Related

Unable to update phone number using elastic search query, getting mapper_parsing_exception

I am trying to update the phone number using the below query, but I am getting "mapper_parsing_exception. Refer the code attached below.
Query:
POST /ps/_update/alOKenkBHofR-Ip1hPcv
{
"doc": {
"ph": {
"na": null,
"nu": "877842376",
"cc": "91",
"ex": null,
"pt": "M"
},
"mdt": "20210615T044700.714Z"
}
Response:
{
"error" : {
"root_cause" : [
{
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [ph] of type [text] in document with id 'alOKenkBHofR-Ip1hPcv'. Preview of field's value: '{cc=91, na=null, ex=null, pt=M, nu=877842376}'"
}
],
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [ph] of type [text] in document with id 'alOKenkBHofR-Ip1hPcv'. Preview of field's value: '{cc=91, na=null, ex=null, pt=M, nu=877842376}'",
"caused_by" : {
"type" : "illegal_state_exception",
"reason" : "Can't get text on a START_OBJECT at 1:3558"
}
},
"status" : 400
}
// code
Document document = Document.create();
Map<String, Object> map = new Phone.ToMap().convert((Phone) value);
document.put(key, map);
UpdateQuery updateQuery = UpdateQuery.builder(id).withDocument(document).build();
UpdateResponse updateResponse = operations.update(updateQuery, indexCoordinates());
Result result = updateResponse.getResult();
Your ph is part of bi object so for updating your document you should do this query:
POST /ps/_update/alOKenkBHofR-Ip1hPcv
{
"doc": {
"bi"{
"ph": {
"na": null,
"nu": "877842376",
"cc": "91",
"ex": null,
"pt": "M"
}
},
"mdt": "20210615T044700.714Z"
}

How to sort multiple fields with exception condition

I cannot use FieldSortBuilder to sort by multiple fields and do the exception condition. So I am wondering can we use painless to do it?
Below is data model.
{ "name" : "string",
"email" : "string",
"schoolNumber" : "number",
"startTime" : "number",
"endTime" : "number",
}
Examples:
{ "name" : "Micheal",
"email" : "mi#gmail.com",
"schoolNumber": 1,
"startTime" : 123,
}
{ "name" : "Racheal",
"email" : "ra#gmail.com",
"schoolNumber": 1,
"startTime" : 456,
"endTime" : 789,
}
{ "name" : "Racheal",
"email" : "ra#gmail.com",
"schoolNumber": 2,
"startTime" : 987,
}
Only endTime is optional. I want to sort all the profiles in startTime by asc, these profiles only have startTime, endTime should inactive and they should have the same schoolNumber.
public static final String SORT_SCRIPT =
"if (doc['endTime.raw'].value == null) {
//sort by startTime which have same schoolNumber
} else {
//sort by endTime which have same schoolNumber
}";
Another solution:
I want to use FieldSortBuilder to set nestedFiler to exclude the endTime
sortBuilder.setNestedFilter(new TermQueryBuilder(LICENSE_ASSIGNMENT_ACTIVATION_TIME_PROPERTY, value:???)
But I don't know how to set value. I have tried with "null" "false" "ScoreMode.None". All failed.
Here is what I've come up with. First let me share you the Elasticsearch query as how this can be done.
Note that I've made use of Exists Query.
Elasticsearch DSL Request
POST <your_index_name>/_search
{
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "endTime"
}
}
]
}
},
"sort": [
{
"startTime": {
"order": "desc"
}
}
]
}
What I've done is simply executed the filter condition on the query level which means using the above query, I only end up with documents without endTime and on these documents am actually executing sorting operation on startTime field.
Below is how its done via Java API.
Java API:
SearchRequest searchRequest = new SearchRequest("<your_index_name>");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//Exists Query
searchSourceBuilder.query(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("endTime")));
//Sort Logic
FieldSortBuilder mySort = SortBuilders.fieldSort("startTime").order(SortOrder.DESC);
searchSourceBuilder.sort(mySort);
searchRequest.source(searchSourceBuilder);
Let me know if this is what you are looking for!

Filter terms query don't work - Elasticseach and the java api

I'm new to stackoverflow
here is my problem
I want to make a request in ES that in first perform a must then a filter. In sql it should lookalike to this below
SELECT * FROM table WHERE name = "the_name" AND type IN ("type1", "type2")
Here is my implementation of this case
#Override
public List<Example> findByName(String pattern, String... types) {
// Prepare query
QueryBuilder queryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("name", pattern))
.filter(QueryBuilders.termsQuery("type", types));
// Execute query
return new ArrayList<>(this.elasticsearchQuery.findAgainstFields(Example.class, queryBuilder));
}
Next, my implementation for method findAgainstFields
#SuppressWarnings("unchecked")
#Override
public <T> List<T> findAgainstFields(Class<?> t, QueryBuilder query) {
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder
.withIndices("my_indice")
.withTypes(t.getSimpleName())
.withSort(new ScoreSortBuilder().order(SortOrder.DESC))
.withQuery(query)
.withPageable(PageRequest.of(0, 5)).build();
// Execute query
return (List<T>) this.elasticsearchTemplate.queryForList(nativeSearchQuery, t);
}
And when I run the project this method (findByName) return an empty array. However, when I remove the .filter(QueryBuilders.termsQuery("type", types)) i got a result. So, on which part i'm wrong?
Thanks in advance
ps: I use ES 5.5 and Java 8 oracle
UPDATE
ES query is this:
{
"bool" : {
"must" : [
{
"term" : {
"name" : {
"value" : "eso",
"boost" : 1.0
}
}
}
],
"filter" : [
{
"terms" : {
"type" : [
"Society",
"Institut"
],
"boost" : 1.0
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
So here, i try to find the data with name as eso with type who can be Society or Institut
the problem was in the mapping file not on java source code.
so i updated the file by changing the type of the property type to keyword (it was text before) and everything works fine.

Error while using matchQuery Elasticsearch

I'm new to elasticsearch and Java.
I have a JSON object like
{
"keyword":null,
"size":[],
"matchResults":
{
"Data": ["first" "Second"]
},
}
I want to search against "matchResults" field and expect output like below:
"Data" : "first"
"Data" : "Second"
"Data" : "first Second"
"Data" : "Second friend"
for getting these results I'm using matchQuery in Java code like this,
Map<String, List<String>> matchResults = request.getMatchResults();
if (matchResults != null) {
for (Map.Entry<String, List<String>> filter : matchResults.entrySet()) {
logger.info("key is" );
List<String> values = filter.getValue();
if (values != null) {
query = query.filter(QueryBuilders.matchQuery(filter.getKey(), values));
}
}
}
But this gives below error
{
"messages": [
"{\"root_cause\":[{\"type\":\"parsing_exception\",\"reason\":\"[match] unknown token [START_ARRAY] after [query]\",\"line\":9,\"col\":23}],\"type\":\"parsing_exception\",\"reason\":\"[match] unknown token [START_ARRAY] after [query]\",\"line\":9,\"col\":23}"
],
"data": null,
"message": "{\"root_cause\":[{\"type\":\"parsing_exception\",\"reason\":\"[match] unknown token [START_ARRAY] after [query]\",\"line\":9,\"col\":23}],\"type\":\"parsing_exception\",\"reason\":\"[match] unknown token [START_ARRAY] after [query]\",\"line\":9,\"col\":23}"
}
Not sure what is causing this.

retrieve values from nested json array in mongodb

My mongo collection has entries in the following format
{
"myobj" : {
"objList" : [
{ "location" : "Texas" },
{ "location" : "Houston"},
{ "name":"Sam" }
]
},
"category" : "cat1"
}
{
"myobj" :
{
"objList" : [
{ "location" : "Tennesy" },
{ "location" : "NY"},
{ "location" : "SF" }
]
},
"category" : "cat2"
}
I want to extract the "**category**" where location is "Houston". In case of simple JSON object I have to just pass it as query like:
BasicDBObject place = new BasicDBObject();
place.put("location", "Houston");
But in case of nested JSON I don't know how to pass it as a query and get the appropriate category. ie If I pass my location as"Houston" then it should return it's appropriate category "cat1"...i hope my question is clear now....
Ok, you have your documents:
db.coll1.insert({
"myobj" : {
"objList" : [
{ "location" : "Texas" },
{ "location" : "Houston"},
{ "name":"Sam" }
]
},
"category" : "cat1"
})
and
db.coll1.insert({
"myobj" : {
"objList" : [
{ "location" : "Tennesy" },
{ "location" : "Houston"},
{ "location" : "SF" }
]
},
"category" : "cat1"
})
Now you can find what you want using the dot operator:
db.coll1.find({"myobj.objList.location": "Texas"}).pretty() will return one object which has Texas
db.coll1.find({"myobj.objList.location": "SF"}).pretty() will return one object which has SF
db.coll1.find({"myobj.objList.location": "Houston"}).pretty() will return both objects
And now I hope you will be able to write it in Java. I have never used Java, but based on this question you can do something like this. If it will not work, just look how to use dot operator in java driver for mongo:
DBCursor cursor = coll1.find(new BasicDBObject("myobj.objList.location", "Texas"));
P.S. you told, that you wanted to retrieve category. In such a way, you will need to use a projection db.coll1.find({<the query I provided}, {category: 1, _id: 0})

Categories