Not able to build query for Elasticsearch using java api - java

Am trying to query elasticsearch via java api for the below elasticsearch query
get my_index12/_search {
"query" : {
"bool": {
"must": [
{
"match": {
"code": {
"query": "TE-7000-8002-W",
"operator": "and"
}
}
},
{
"match": {
"locale": {
"query": "en_US",
"operator": "and"
}
}
}
]
}
}
}
The above query is working fine is Kibana. Am trying to replicate the same query using Elasticsearch Java API.
Please find my JAVA API query that am trying to build.
QueryBuilder qb = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("code",name)).operator(Operator.AND);
Am getting the below error from eclipse.
The method operator(Operator) is undefined for the type BoolQueryBuilder
Am using Elasticsearch 6.2.3 version

In java transport client, search request can be build both in QueryBuilders and XContent format which build query param in json format.
With QueryBuilder, especially BoolQuery, the operator in query dsl is represented by either must() (means and operator) or should() (means or operator).
As described, your query can be represented like:
QueryBuilders.boolQuery().must().must().build();
One more interesting question is how to present the following query DSL:
{
"query": {
"bool": {
"must": [{
"term": {
"field1": "value"
}
}, {
"match": {
"filed2": "value"
}
}],
"should": [{
"term": {
"field3": "value"
}
},{
"term": {
"field4": "value"
}]
}
}
}
once you can understand the demo query DSL and successfully implement it with java API, means you are getting to know Java Transport client API.
hope can offer you some help

Related

How to write custom Elasticsearch Query in Java?

This is my query on Elasticsearch,
GET index101/_search
{
"query": {
"function_score": {
"boost_mode": "replace",
"query": {
"constant_score": {
"filter": {
"terms": {
"fields": ["767","434", "101", "222"]
}
}
}
},
"pqcode_score": {
"descriptors": [
{
"descriptor": "base64string"
}
],
"pqparams": {
"bucket_field": "fields",
"pqcode_field": "fields2",
"distance_function": "similarity",
"model": "random"
}
}
}
}
}
Looked into the documentation of Elasticsearch with Java, but couldn't find anything that could resolve this query in Java.
I created a JSON file, and got the input query in the jsonObject and then passed it as a parameter to searchSourceBuilder.query().
But it gives the error that the jsonObject can't be converted into QueryBuilder.
How can we go ahead with this query in Java?
Is there any other workaround for this?
looks like pqcode_score is your custom key in the Elasticsearch query, and you are trying to add the custom component/constructs in your Elasticsearch query thats not possible, hence you are getting the error.
You need to use the constructs in your Elasticsearch query thats supported by Elasticsearch.

Elastic Search: Boost Results with "Exact match" in "query_string" without specifying the field

I am using query_string to search for records from Elastic,
Example Query :
GET /stories_qa/_search
{
"query": {
"query_string": {
"query": "Johnson && Johnson"
}
}
}
This query gives me relevant records, but the exact match record is not on top, I figured out on how we can boost records based on specific fields, but in my case, I don't want to provide field and make search restrictive, Is there an option in ElasticSearch to achieve the same.
You can probably do something like below, but do thorough testing and test multiple scenarios before you move it to production.
POST <your_index_name>/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"query_string": {
"query": "\"Karnataka Delhi\"",
"default_operator": "AND"
}
}
]
}
},
{
"query_string": {
"query": "Karnataka Delhi",
"default_operator": "OR",
"boost": 2
}
},
{
"query_string": {
"query": "Karnataka Delhi",
"default_operator": "AND",
"boost": 4
}
}
]
}
}
}
Hope this helps!
It would help with examples, but you can use phrase_match query by adding double quote. If you add a boost to the phrase_match query you will be able to get to exact match ranked higher.
The following query should do what you want.
GET /stories_qa/_search
{
"query": {
"query_string": {
"query": "(\"Johnson && Johnson\")^2 OR (Johnson && Johnson)"
}
}
}

Elastic search exact match query issue

I am having a problem while querying elastic search. The below is my query
GET _search {
"query": {
"bool": {
"must": [{
"match": {
"name": "SomeName"
}
},
{
"match": {
"type": "SomeType"
}
},
{
"match": {
"productId": "ff134be8-10fc-4461-b620-79s51199c7qb"
}
},
{
"range": {
"request_date": {
"from": "2018-08-22T12:16:37,392",
"to": "2018-08-28T12:17:41,137",
"format": "YYYY-MM-dd'T'HH:mm:ss,SSS"
}
}
}
]
}
}
}
I am using three match queries and a range query in the bool query. My intention is getting docs with these exact matches and with in this date range. Here , if i change name and type value, i wont get the results. But for productId , if i put just ff134be8, i would get results. Anyone knows why is that ? . The exact match works on name and type but not for productId
You need to set the mapping of your productId to keyword to avoid the tokenization. With the standard tokenizer "ff134be8-10fc-4461-b620-79s51199c7qb" will create ["ff134be8", "10fc", "4461", "b620", "79s51199c7qb"] as tokens.
You have different options :
1/ use a term query to check without analyzing the content of the field
...
{
"term": {
"productId": "ff134be8-10fc-4461-b620-79s51199c7qb"
}
},
...
2/ if you are in Elasticsearch 6.X you could change your request to
...
{
"match": {
"productId.keyword": "ff134be8-10fc-4461-b620-79s51199c7qb"
}
},
...
As elasticsearch will create a subfield keyword with the type keyword for all string field
The best option is, of course, the first one. Always use term query if you are trying to match the exact content.

Querying ElasticSearch using a JSON file through JAVA API

I have a query in valid JSON format which works well in kibana or Sense when I use GET request.I am also able to create this query using XContentBuilder, but I need to send this query using its JSON form as it is to ElasticSearch. Is it possible to store the query in a JSON file and query ElasticSearch using this JSON file.
My query -
{
"min_score":5,
"sort" : [
{
"_geo_distance" : {
"location" : [40.715, -73.988],
"order" : "asc",
"unit" : "km",
"mode" : "min",
"distance_type" : "arc"
}
}
],
"query": {
"bool": {
"must": {
"query_string": {
"query": "hospital",
"analyzer": "english"
}
},
"filter": {
"geo_distance": {
"distance": "50000km",
"location": {
"lat": 40.715,
"lon": -73.988
}
}
}
}
}
}
What I want is to store this query in a JSON file and use this JSON file to send a search request directly without using Query builder.
You can use a search template, and store this template in the cluster state, see the official documentation about search templates, especially about pre-registered templates.

Function score query with field_value_factor on not (yet) existing field

I've been messing around with this problem for quite some time now and can't get round to fixing this.
Take the following case:
I have 2 employees in my company which have their own blog page:
POST blog/page/1
{
"author": "Byron",
"author-title": "Junior Software Developer",
"content" : "My amazing bio"
}
and
POST blog/page/2
{
"author": "Jason",
"author-title": "Senior Software Developer",
"content" : "My amazing bio is better"
}
After they created their blog posts, we would like to keep track of the 'views' of their blogs and boost search results based on their 'views'.
This can be done by using the function score query:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"author-title": "developer"
}
},
"functions": [
{
"filter": {
"range": {
"views": {
"from": 1
}
}
},
"field_value_factor": {
"field": "views"
}
}
]
}
}
}
I use the range filter to make sure the field_value_factor doesn't affect the score when the amount of views is 0 (score would be also 0).
Now when I try to run this query, I will get the following exception:
nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }]
Which makes sense, because the field doesn't exist anywhere in the index.
If I were to add views = 0 on index-time, I wouldn't have the above issue as the field is known within the index. But in my use-case I'm unable to add this either on index-time or to a mapping.
Based on the ability to use a range filter within the function score query, I thought I would be able to use a exists filter to make sure that the field_value_factor part would only be executed when the field is actually present in the index, but no such luck:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"author-title": "developer"
}
},
"functions": [
{
"filter": {
"bool": {
"must": [
{
"exists": {
"field": "views"
}
},
{
"range": {
"views": {
"from": 1
}
}
}
]
}
},
"field_value_factor": {
"field": "views"
}
}
]
}
}
}
Still gives:
nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }]
Where I'd expect Elasticsearch to apply the filter first, before parsing the field_value_factor.
Any thoughts on how to fix this issue, without the use of mapping files or fixing during index-time or scripts??
The error you're seeing occurs at query parsing time, i.e. nothing has been executed yet. At that time, the FieldValueFactorFunctionParser builds the filter_value_factor function to be executed later, but it notices that the views field doesn't exist in the mapping type.
Note that the filter has not been executed yet, just like the filter_value_factor function, it has only been parsed by FunctionScoreQueryParser.
I'm wondering why you can't simply add a field in your mapping type, it's as easy as running this
curl -XPUT 'http://localhost:9200/blog/_mapping/page' -d '{
"page" : {
"properties" : {
"views" : {"type" : "integer"}
}
}
}'
If this is REALLY not an option, another possibility would be to use script_score instead, like this:
{
"query": {
"function_score": {
"query": {
"match": {
"author-title": "developer"
}
},
"functions": [
{
"filter": {
"range": {
"views": {
"from": 1
}
}
},
"script_score": {
"script": "_score * doc.views.value"
}
}
]
}
}
}

Categories

Resources