ElasticSearch span near query not producing expected results with nested span queries - elasticsearch

I have an odd scenario. I have a document which contains the text "6 Music Live Hour".
The second part of the query - span_term matching "Hour" produces no results when written as below
{
"span_near" : {
"clauses" : [
{
"span_near" : {
"clauses" : [
{
"span_term" : {
"all_field" : {
"value" : "6",
"boost" : 1.0
}
}
},
{
"span_multi" : {
"match" : {
"wildcard" : {
"all_field" : {
"wildcard" : "M*c",
"boost" : 1.0
}
}
},
"boost" : 1.0
}
}
],
"slop" : 0,
"in_order" : true,
"boost" : 1.0
}
},
{
"span_term" : {
"all_field" : {
"value" : "Hour",
"boost" : 1.0
}
}
}
],
"slop" : 2147483647,
"in_order" : true,
"boost" : 1.0
}
}
However, when I change this to a wildcard query it produces the expected result. See below.
{
"span_near" : {
"clauses" : [
{
"span_near" : {
"clauses" : [
{
"span_term" : {
"all_field" : {
"value" : "6",
"boost" : 1.0
}
}
},
{
"span_multi" : {
"match" : {
"wildcard" : {
"all_field" : {
"wildcard" : "M*c",
"boost" : 1.0
}
}
},
"boost" : 1.0
}
}
],
"slop" : 0,
"in_order" : true,
"boost" : 1.0
}
},
{
"span_multi" : {
"match" : {
"wildcard" : {
"all_field" : {
"wildcard" : "Hour",
"boost" : 1.0
}
}
},
"boost" : 1.0
}
}
],
"slop" : 2147483647,
"in_order" : true,
"boost" : 1.0
}
}
Please can anyone advise on what I'm doing incorrectly in the first query.

Converting the text to lowercase and then building the term query produced the expected results.

Related

How do I query nested with normal match query together?

I want to fire nestedQuery on addresses and multiMatchQuery on name in single query. I tried few ways but I am getting "[bool] query does not support [nested]". I don't know whether this is possible or not (ES version: 7.x).
When I separately querying (i.e.nestedQuery() & multiMatchQuery()) that time it is working fine.
Please help me with that.
This is the mapping I am using:
{
"employee" : {
"mappings" : {
"properties" : {
"addresses" : {
"type" : "nested",
"properties" : {
"permanentAddress" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"TemporaryAddress" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
1. {
"query": {
"nested": {
"path": "addresses",
"query": {
"bool": {
"must": [
{ "match": { "addresses.permanentAddress": "xxx" } }
]
}
},
"score_mode": "avg"
}
}
}
2. {
"query": {
"bool": {
"must" : [
{
"multi_match" : {
"query" : "xxx",
"fields" : [
"name^1.0"
],
"type" : "best_fields",
"boost" : 1.0
}
}
]
}
}
}
nestedQuery() = looking for xxx value in addresses.permanentAddress
multi_match() = looking for xxx value in name
If value of name or addresses.permanentAddress matches with xxx then returns the result.
"bool" : {
"should" : [
{
"bool" : {
"must" : [
{
"match" : {
"name" : {
"query" : "xxx",
"operator" : "AND",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : true,
"lenient" : false,
"zero_terms_query" : "NONE",
"auto_generate_synonyms_phrase_query" : true,
"boost" : 1.0
}
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
{
"nested" : {
"query" : {
"bool" : {
"must" : [
{
"match" : {
"employee.permanentAddress" : {
"query" : "xxx",
"operator" : "AND",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : true,
"lenient" : false,
"zero_terms_query" : "NONE",
"auto_generate_synonyms_phrase_query" : true,
"boost" : 1.0
}
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"path" : "employee",
"ignore_unmapped" : false,
"score_mode" : "none",
"boost" : 1.0,
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
This Bool query with nested worked for me and with that I can able to check parent's as well as nested property.

How to built AND condition between should and must elastic search bool query

Here is the sample USER document
{
"id" : "1234567",
"userId" : "testuser01",
"firstName" : "firstname",
"lastName" : "lastname",
"orgId" : "567890",
"phoneNumber" : "1234567890"
}
I want to build a search query where in I want to pull all those users which belong to particular orgId AND which matches the search text entered by user in any of the fields (userId, firstname, etc.)
ex. if search is made using text "first", I want to pull all those records which belong to particular orgId AND fields containing first in it.
Sample query I am trying is
"query" : {
"bool" : {
"must" : [
{
"term" : {
"orgId.keyword" : {
"value" : "567890",
"boost" : 1.0
}
}
}
],
"should" : [
{
"simple_query_string" : {
"query" : "first*",
"fields" : [
"lastName^1.0"
],
"flags" : -1,
"default_operator" : "or",
"lenient" : false,
"analyze_wildcard" : true,
"boost" : 1.0
}
},
{
"simple_query_string" : {
"query" : "first*",
"fields" : [
"userId^1.0"
],
"flags" : -1,
"default_operator" : "or",
"lenient" : false,
"analyze_wildcard" : true,
"boost" : 1.0
}
},
{
"simple_query_string" : {
"query" : "first*",
"fields" : [
"orgId^1.0"
],
"flags" : -1,
"default_operator" : "or",
"lenient" : false,
"analyze_wildcard" : true,
"boost" : 1.0
}
},
{
"simple_query_string" : {
"query" : "first*",
"fields" : [
"firstName^1.0"
],
"flags" : -1,
"default_operator" : "or",
"lenient" : false,
"analyze_wildcard" : true,
"boost" : 1.0
}
},
{
"simple_query_string" : {
"query" : "first*",
"fields" : [
"phoneNumber^1.0"
],
"flags" : -1,
"default_operator" : "or",
"lenient" : false,
"analyze_wildcard" : true,
"boost" : 1.0
}
},
{
"simple_query_string" : {
"query" : "first*",
"fields" : [
"id^1.0"
],
"flags" : -1,
"default_operator" : "or",
"lenient" : false,
"analyze_wildcard" : true,
"boost" : 1.0
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"sort" : [
{
"userId.keyword" : {
"order" : "asc"
}
}
]
}
Issue I am facing is, I want to have AND condition between MUST and SHOULD.
You don't need to specify the query for each field in query_string query. Rather you can specify the list of fields as below:
{
"query": {
"bool": {
"must": [
{
"term": {
"orgId.keyword": {
"value": "567890",
"boost": 1
}
}
},
{
"simple_query_string": {
"query": "first*",
"fields": [
"lastName^1.0",
"userId^1.0",
"orgId^1.0",
"firstName^1.0",
"phoneNumber^1.0",
"id^1.0"
]
}
}
]
}
},
"sort": [
{
"userId.keyword": {
"order": "asc"
}
}
]
}
Also to answer
How to built AND condition between should and must elastic search bool query?
here is a sample query for this:
{
"query": {
"bool": {
"must": [
{
"term": {
"field1": "someval"
}
},
{
"bool": {
"should": [
{
"terms": {
"field2": [
"v1",
"v2"
]
}
},
{
"query_string": {
"query": "this AND that OR thus"
}
}
]
}
}
]
}
}
}

ElasticSearch should query

I want to create ElasticSearch query which would be the same as this SQL query
select *
from main.adverts
where user_id = 4
and
(title ilike '%продать / купить%'
or description ilike '%продать / купить%'
)
My attempt is:
{
"query" :{
"bool" : {
"must" : [
{
"term" : {
"user.id" : {
"value" : 4,
"boost" : 1.0
}
}
}
],
"should" : [
{
"bool" : {
"must" : [
{
"match" : {
"title" : {
"query" : "продать",
"operator" : "OR",
"fuzzy_transpositions" : false,
"boost" : 1.0
}
}
},
{
"wildcard" : {
"title" : {
"wildcard" : "купить*",
"boost" : 1.0
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
{
"bool" : {
"must" : [
{
"match" : {
"description" : {
"query" : "продать",
"operator" : "OR",
"fuzzy_transpositions" : false,
"boost" : 1.0
}
}
},
{
"wildcard" : {
"description" : {
"wildcard" : "купить*",
"boost" : 1.0
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
}
But it doesn't work correctly. As the result of this query I got records which doesn't contain phrase "продать / купить".
I think that problem is in the "should" part of ElasticSearch query but can't get where is particular.
Could you point me where is my mistake?
It seems that I've found solution
{
"from" : 0, "size" : 60,
"_source" : ["title", "description"],
"query" :{
"bool" : {
"must" : [
{
"term" : {
"user.id" : {
"value" : 4,
"boost" : 1.0
}
}
},
{
"bool" : {
"must" : [
{
"match" : {
"title" : {
"query" : "продать",
"operator" : "OR",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : false,
"lenient" : false,
"zero_terms_query" : "NONE",
"boost" : 1.0
}
}
},
{
"wildcard" : {
"title" : {
"wildcard" : "купить*",
"boost" : 1.0
}
}
}
],
"should" : [
{
"bool" : {
"must" : [
{
"match" : {
"description" : {
"query" : "продать",
"operator" : "OR",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : false,
"lenient" : false,
"zero_terms_query" : "NONE",
"boost" : 1.0
}
}
},
{
"wildcard" : {
"description" : {
"wildcard" : "купить*",
"boost" : 1.0
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
}

elasticsearch mix "and filter" with "bool filter"

i work on elasticsearch, I try to mix two working queries. the first with "and filter" and the second with "bool filter" but i fail.
My queries are generated dynamically from a user interface.
the "and filter" :
I need "and filter" to query data, for example a field have to be equal to "africa" or "asia" or empty. this is an example of working query :
curl -XGET 'http://localhost:9200/botanique/specimens/_search?pretty' -d '
{
"fields" : ["D_TYPESTATUS", "O_HASMEDIA"],
"aggs" : {
"D_TYPESTATUS_MISSING" : {
"missing" : {
"field" : "D_TYPESTATUS"
}
},
"D_TYPESTATUS" : {
"terms" : {
"field" : "D_TYPESTATUS",
"size" : 10
}
}
},
"query" : {
"filtered" : {
"filter" : {
"and" : [
{ "or" : [{
"term" : {
"O_HASMEDIA" : "true"
}
}
]
}, {
"or" : [{
"term" : {
"T_GENUS" : "flemingia"
}
}
]
}, {
"or" : [{
"term" : {
"L_CONTINENT" : "africa"
}
}, {
"term" : {
"L_CONTINENT" : "asia"
}
}, {
"missing" : {
"field" : "L_CONTINENT"
}
}
]
}, {
"or" : [{
"term" : {
"I_INSTITUTIONCODE" : "mnhn"
}
}
]
}
]
}
}
}
}'
this query work fine, this is the result :
"hits" : {
"total" : 1006,
"max_score" : 1.0,
"hits" : [ {
"_index" : "botanique",
"_type" : "specimens",
"_id" : "9459AB31EC354F1FAE270BDB6C22CDF7",
"_score" : 1.0,
"fields" : {
"O_HASMEDIA" : [ true ],
"D_TYPESTATUS" : "syntype"
}
},
....
},
"aggregations" : {
"D_TYPESTATUS" : {
"buckets" : [ {
"key" : "syntype",
"doc_count" : 6
}, {
"key" : "type",
"doc_count" : 5
}, {
"key" : "isotype",
"doc_count" : 2
} ]
},
"D_TYPESTATUS_MISSING" : {
"doc_count" : 993
}
}
}
the second query :
Now i need to restrict the result data with the field : "D_TYPESTATUS" who must be different from the value "type" and must be not null.
this query work to do this :
curl -XGET 'http://localhost:9200/botanique/specimens/_search?size=10&pretty' -d ' {
"fields" : ["D_TYPESTATUS", "O_HASMEDIA"],
"aggs" : {
"D_TYPESTATUS_MISSING" : {
"missing" : {"field" : "D_TYPESTATUS"}
},
"D_TYPESTATUS" : {
"terms" : {"field" : "D_TYPESTATUS","size" : 20}
}
},
"query" : {
"filtered" : {
"query" : {
"query_string" : { "query" : "liliaceae" }
},
"filter" : {
"bool" : {
"must_not" : [{
"term" : {
"D_TYPESTATUS" : "type"
}
}
],
"must":{
"exists" : {
"field" : "D_TYPESTATUS"
}
}
}
}
}
}
}'
and the result :
{[ {
"_index" : "botanique_tmp2",
"_type" : "specimens",
"_id" : "0C388B4A3186410CBA46826BA296ECBC",
"_score" : 0.9641713,
"fields" : {
"D_TYPESTATUS" : [ "isotype" ],
"O_HASMEDIA" : [ true ]
}
} , ... ]},
"aggregations" : {
"D_TYPESTATUS" : {
"buckets" : [ {
"key" : "isotype",
"doc_count" : 40
}, {
"key" : "syntype",
"doc_count" : 37
}, {
"key" : "holotype",
"doc_count" : 6
}, {
"key" : "paratype",
"doc_count" : 3
}, {
"key" : "isonéotype",
"doc_count" : 2
} ]
},
"D_TYPESTATUS_MISSING" : {
"doc_count" : 0
}
}
how to integret the "bool filter" in the "and filter" ??
thanks a lot
I must be missing something, because it's easy:
{
"query": {
"filtered": {
"filter": {
"and": [
{
"or": [
{
"term": {
"O_HASMEDIA": "true"
}
}
]
},
{
"or": [
{
"term": {
"T_GENUS": "flemingia"
}
}
]
},
{
"or": [
{
"term": {
"L_CONTINENT": "africa"
}
},
{
"term": {
"L_CONTINENT": "asia"
}
},
{
"missing": {
"field": "L_CONTINENT"
}
}
]
},
{
"or": [
{
"term": {
"I_INSTITUTIONCODE": "mnhn"
}
}
]
},
{
"bool": {
"must_not": [
{
"term": {
"D_TYPESTATUS": "type"
}
}
],
"must": {
"exists": {
"field": "D_TYPESTATUS"
}
}
}
}
]
}
}
}
}

ElasticSearch - Boost score for fuzzy words

I want perform fuzzy search on user search words(apple iphone 5s). I want to give more score value to first(apple), little less for second and so on.
I started with the query given below but not working as I expected:
{
"query": {
"fuzzy_like_this_field": {
"name": {
"like_text": "appla^4 iphane^2 5^1",
"max_query_terms": 12
}
}
},
"fields": "name",
"sort": {
"_score": {
"order": "desc"
}
}
}
May I know how to write this query??
I found the answer.
{
"query" : {
"bool" : {
"should" : [
{
"fuzzy" : {
"name" : {
"min_similarity" : 0.5,
"boost" : 4,
"value" : "appla",
"prefix_length" : 0
}
}
},
{
"fuzzy" : {
"name" : {
"min_similarity" : 0.1,
"boost" : 2,
"value" : "iphane",
"prefix_length" : 1
}
}
} ,
{
"fuzzy" : {
"name" : {
"min_similarity" : 0.1,
"boost" : 1,
"value" : "5",
"prefix_length" : 1
}
}
}
]
}
}
}

Resources