In elastic search, q=joh* is returning a correct set, but a JSON with match: joh* is not - elasticsearch

When I call this URL:
http://192.168.x.x:9200/identities/work/_search?q=joh*
ES is returning a limited (5) set of matches, starting with some indexes of people names John and Johnny etc. That seems to be the correct result.
But when I send this JSON to ES:
{
"query": {
"match": {
"_all": "joh*"
}
}
}
I get results that I can't even logically explain. Seems rather random, and a lot of indexes too (hundreds, not a lot of johns and johnny's either ;))
Is this not the equivalent of the URL mentioned above? What am I doing wrong?

When you call the following URL, what ES does implicitly is to create a query_string query not a match query
http://192.168.x.x:9200/identities/work/_search?q=joh*
So the equivalent JSON query would be:
{
"query": {
"query_string": {
"query": "joh*"
}
}
}
Moreover, match queries do not handle wildcards as in joh*, the * is considered and matched as a real character, not as a wildcard.

Related

Elatisearch match_phrase_prefix query, with exact prefix match

I have a match_phrase_prefix query, which works as expected. But when the users passes any special characters at the end of the keyword, ES ignores these characters, and still returns the result.
query{ match_phrase_prefix:{ content: { query: searchTerm } } }
I am using this query to search for prefix. If i pass a term like overflow####!! ES is returning me all the results with the word overflow in it. But instead i want to make an exact prefix match, where the special characters are not ignored. The search term could be of multiple words as well stack overflow search.
How could i make ES search of prefix_match without ignoring the special_chars.
You can use keyword analyzer when defining your query.
{
"query": {
"match_phrase_prefix": {
"content": {
"query": "overflow####!!",
"analyzer": "keyword"
}
}
}
}

Find one result based on a term query or a list of results based on a match query

I have an index of documents, each containing an id and name field. Each document name happens to be unique.
I want to perform a query on the name field that returns one exact result if possible, or falls back to return a list of similar results. For example, if the search term is Acme Incorporated and there is an exact result, return that only. Otherwise return similar matches; e.g: ACME Inc., acme, Ace etc.
I assumed that I need to somehow combine a keyword-based term query for an exact match, and a text-based match query for the similar matches. I am still getting to grips with compound queries so my first attempt was pretty naive:
{
"query": {
"bool": {
"should": [
{
"term": {
"name.exact": "Acme Incorporated"
}
},
{
"match": {
"name": "Acme Incorporated"
}
}
]
}
}
}
This returns a list of similar matches AND an exact match if present, because at least one query should succeed. This is obviously not correct.
In order to facilitate the keyword-based term query above, I added name.exact to my document mapping:
{
"mappings": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "text",
"fields": {
"exact": {
"type": "keyword"
}
}
}
}
}
}
I suppose another approach is use the Multi Search API to perform the above queries separately. This allows me to look at the responses, and decide to use the match query if the term query result set is empty. This will work for my use case but I suspect that this is not an optimal approach.
I assume this is a common use-case but I am not sure what the solution is.
Edit
My current thinking on this is that I go with a Multi Search query as described above, the first is the same keyword-based term query to attempt to find an exact result and the second is the following — a compound bool query that excludes an exact result.
{
"query": {
"bool": {
"must": {
"match": {
"name": "Acme Incorporated"
}
},
"must_not": {
"term": {
"name.keyword": "Acme Incorporated"
}
}
}
}
}
In the end, the MultiSearch API suited my use case:
The multi search API executes several searches from a single API request. The format of the request is similar to the bulk API format and makes use of the newline delimited JSON (NDJSON) format.
I used this to perform two queries in one request:
Find any exact results with a keyword-based term query on the document name field.
Find any similar results with a bool query, comprising a match query on the
document name field, and a must_not of the first query to
filter out any exact results.
A Multi Search body is constructed of one or more pairs of an (optionally) empty header and body (a single query) delimited by newlines; e.g:
GET /myindex/_msearch
{}
{"query": {"constant_score": {"filter": {"term": {"name.keyword": "Acme Incorporated"}}}}}
{}
{"query": {"bool": {"must": {"match": {"name": "Acme Incorporated"}}, "must_not": {"term": {"name.keyword": "Acme Incorporated"}}}}}
The query is in ndjson format, which states that "Each Line is a Valid JSON Value". This requires that each query be compressed to one line, which is not very readable but not an issue if you're using a library to construct queries.

How to match multiple words via terms in elasticsearch

My query for matching multiple words is as following,
{"query":
{"bool":{"must":[{"terms":{"my_field":"word1 word2"}}]}
upon execution, the result set is empty though data exists for the following query.
Instead of above query, if I use
{"bool":{"must":[{"terms":{"my_field":"word1"}}]}
then elastic-search is returning data.
How to match the complete sentence?
Based on your comment on the above answer, I believe you should simply use two term queries inside your must query array.
{
"query":
{ "bool" :
{
"must":[
{"term":{"my_field": "word1" } },
{"term":{"my_field": "word2" } }
]
}
}
}
you can try to put the words in an array and see if it works.
Like this:
{"query": {"bool":{"must":[{"terms":{"my_field":["word1", "word2"]}}]}
here is the documentation: https://www.elastic.co/guide/en/elasticsearch/guide/current/_finding_multiple_exact_values.html
Hope it works =)

Query-Term and Filter-Term Return Zero Results on an Exact Match, but Query-Match Returns a Result. Why?

Given:
I loaded an instance into ElasticSearch which has its placeId property set to "Foo".
And I run the following searches:
{
"query": {
"term": {
"placeId": {
"value": "Foo"
}
}
}
}
{
"filter": {
"term": {
"placeId": "Foo"
}
}
}
{
"query": {
"match": {
"placeId": {
"query": "Foo"
}
}
}
}
But of these three, only the third one returned a result.
Why is this? Shouldn't they all have returned a result?
By default, using the standard analyzer, ES places your "Foo" in an index as "foo" (meaning, lowercased). When searching for term, ES doesn't use an analyzer so, it is actually searching for "Foo" (exact case). Whereas, in its index the "foo" exists (because of the analyzer).
The value passed for match instead is analyzed and ES is actually searching for "foo" in its indices, not "Foo" as it does with term.
So, the behavior you see is normal and this is how it's supposed to work.
Here about match:
A family of match queries that accept text/numerics/dates, analyzes it, and constructs a query out of it.
Here about term:
Matches documents that have fields that contain a term (not analyzed).
If u are not used an analyzer means elastic search term query and term query Filter should not support the Upper case Value. Please use "foo" in Your Query. please use this way
curl -XGET localhost:9200/index/incident/_search -d '{
"query":{
"term":{"field1":{"value":"value1"}
}}}'
but match all query is support upper and lower case.
Hope it will work.

Elasticsearch: how to perform exact match on wildcard field

We used the following query to get exact match on wildcard field:
"query_string": {
"query": "\"abcd\"",
"fields": [
"*.Name"
]
}
}
but it returned results also for values, such as: abcde, abcd1, etc...
Does anyone has an idea how to get an exact match in such case? We tried to add "analyzer:simple", which made things worse and sometimes didn't return results at all.
Thanks in advance.

Resources