multi_match query returning no results elasticsearch - elasticsearch

I am trying a multi_match query in ElasticSearch but the query is returning no results. The query is:
curl -XPOST "http://localhost:9200/smartjn/feed_details/_search" -d'
{
"query" : {
"multi_match" : {
"query" : "Dho*",
"fields" : [ "title", "wardname" ]
}
}
}'
{"took":11,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}}
I have value in wardname field starting with Dho,
{
_id: ObjectId("56f43c0344fc86e73b1170b0"),
title: "Constant road work",
approvalStatus: "approved",
subward: "56a6124244fc868a255fe3fe",
wardname: "Dhokali"
}
not sure why is it not returning anything. Any help greatly appreciated.
Thanks

You need to use Phrase Prefix query if you want to search something that starts with some string. Try following query.
curl -XPOST "http://localhost:9200/smartjn/feed_details/_search" -d'
{
"query" : {
"multi_match" : {
"query" : "Dho*",
"fields" : [ "title", "wardname" ],
"type': 'phrase_prefix"
}
}
}'

Related

Don't make some fields searchable when using query_string or term/terms in Elasticsearch

Having this mapping:
curl -XPUT 'localhost:9200/testindex?pretty=true' -d '{
"mappings": {
"items": {
"dynamic": "strict",
"properties" : {
"title" : { "type": "string" },
"body" : { "type": "string" },
"tags" : { "type": "string" }
}}}}'
I add two simple items:
curl -XPUT 'localhost:9200/testindex/items/1' -d '{
"title": "This is a test title",
"body" : "This is the body of the java",
"tags" : "csharp"
}'
curl -XPUT 'localhost:9200/testindex/items/2' -d '{
"title": "Another text title",
"body": "My body is great and Im super handsome",
"tags" : ["cplusplus", "python", "java"]
}'
If I search the string java:
curl -XGET 'localhost:9200/testindex/items/_search?q=java&pretty=true'
... it will match both items. The first item will match on the body and the other one on the tags.
How can I avoid to search in some fields? In the example I dont know it to match with the field tags. But I want to maintain tags indexed as I use them for getting aggregations.
I know I can do it using this:
{
"query" : {
"query_string": {
"query": "java AND -tags:java"
}},
"_source" : {
"exclude" : ["*.tags"]
}
}'
But is there any other more elegant way, like putting something in the mapping?
PS: My searches are always query_strings and term / terms and I'm using ES 2.3.2
You can specify fields option if you only want to match against certain fields
{
"query_string" : {
"fields" : ["body"],
"query" : "java"
}
}
EDIT 1
You could use the "include_in_all": false param inside mapping. Check the documentation. Query string query defaults to _all so you can add "include_in_all": false to all the fields in which you don't want match and after that this query would only look in body field
{
"query_string" : {
"query" : "java"
}
}
Does this help?

Elasticsearch - "OR" query condition using match query and term query

I have following match query string:
curl -XGET 'my-es.com/my_indice/_search?pretty' -d '{
"size" : 10,
"query" : {
"bool" : {
"must" : [ {
"match" : {
"state" : {
"query" : ["ACTIVE", "INACTIVE"],
"type" : "boolean"
}
}
}]
}
}
}'
I guess it means "state" = "ACTIVE" or "state" = "INACTIVE", but actually it performs "state" = "INACTIVE".
Then I tried term query string:
curl -XGET 'my-es.com/my_indice/_search?pretty' -d '{
"size" : 10,
"query" : {
"bool" : {
"must" : [{
"terms" : { "state" : ["ACTIVE", "INACTIVE"] }
}]
}
}
}'
It performs "state" = "ACTIVE" or "state" = "INACTIVE", showing term query supports multiple OR conditions via an array.
I'm curious about why match query does not support OR condition via an array? And it does not show any syntax error.
The match query only supports a single string value to be specified. It is not explicitly specified in the official match documentation, but if you're willing to read some source code for MatchQueryParser.java, you can see that while parsing the query field, the parser will skip the tokens delimiting the start and end of the array and always override the value with the latest one being parsed, hence why you're seeing what you see, i.e. that state will be matched with INACTIVE only.
What you can do, however, is to put both tokens inside the same string like below, and both tokens will be taken into account:
curl -XGET 'my-es.com/my_indice/_search?pretty' -d '{
"size" : 10,
"query" : {
"bool" : {
"must" : [ {
"match" : {
"state" : {
"query" : "ACTIVE INACTIVE",
"type" : "boolean"
}
}
}]
}
}
}'

Fuzzy string matching using Levenshtein algorithm in Elasticsearch

I have just started exploring Elasticsearch. I created a document as follows:
curl -XPUT "http://localhost:9200/cities/city/1" -d'
{
"name": "Saint Louis"
}'
I now tried do a fuzzy search on the name field with a Levenshtein distance of 5 as follows :
curl -XGET "http://localhost:9200/_search " -d'
{
"query": {
"fuzzy": {
"name" : {
"value" : "St. Louis",
"fuzziness" : 5
}
}
}
}'
But its not returning any match. I expect the Saint Louis record to be returned. How can i fix my query ?
Thanks.
The problem with your query is that only a maximum edit distance of 2 is allowed.
In the case above what you probably want to do is have a synonym for St. to Saint, and that would match for you. Of course, this would depend on your data as St could also be "street".
If you want to just test the fuzzy searching, you could try this example
curl -XGET "http://localhost:9200/_search " -d'
{
"query": {
"fuzzy": {
"name" : {
"value" : "Louiee",
"fuzziness" : 2
}
}
}
}

ElasticSearch has_parent query

I am experimenting with Elasticsearch parent/child with some simple examples from fun-with-elasticsearch-s-children-and-nested-documents/. I am able to query child elements by running the query in the blog
curl -XPOST localhost:9200/authors/bare_author/_search -d '{
However, I could not tweak the example for has_parent query. Can someone please point what I am doing wrong, as I keep getting 0 results.
This is what I tried
#Returns 0 hits
curl -XPOST localhost:9200/authors/book/_search -d '{
"query": {
"has_parent": {
"type": "bare_author",
"query" : {
"filtered": {
"query": { "match_all": {}},
"filter" : {"term": { "name": "Alastair Reynolds"}}
}
}
}
}
}'
#did not work either
curl -XPOST localhost:9200/authors/book/_search -d '{
"query": {
"has_parent" : {
"type" : "bare_author",
"query" : {
"term" : {
"name" : "Alastair Reynolds"
}
}
}
}
}'
This works with match but its just matching the first name
#works but matches just first name
curl -XPOST localhost:9200/authors/book/_search -d '{
"query": {
"has_parent" : {
"type" : "bare_author",
"query" : {
"match" : {"name": "Alastair"}
}
}
}
}'
I suppose you are using the default mappings, thus analysing the name field using the standard analyzer. On the other hand, term query and term filter don't support text analysis thus you search for the token Alastair Reynolds while in the index you have alastair and reynolds as two different tokens and lowercased.
The match query returns result because it's analyzed, thus underneath lowercased and it finds matches. You can just change your term query and make it a match query, it will find matches even with multiple terms, because in that case it will be tokenized on whitespaces and will generate a boolean or dismax query out of the different terms provided.

How to search for a term and match a boolean condition

I've had good success getting results for searches using the below syntax, but I'm having trouble adding a boolean condition.
http://localhost:9200/index_name/type_name/_search?q=test
My documents look like:
{
"isbn":"9780307414922",
"name":"Dark of the Night",
"adult":false
}
Here's my best guess as to how to achieve what I'm trying to do.
{
"query_string": {
"default_field": "_all",
"query": "test"
},
"from": 0,
"size": 20,
"terms": {
"adult": true
}
}
However this results in "Parse Failure [No parser for element [query_string]]]; }]"
I'm using elastic search 0.20.5.
How can I match documents containing a search term the way "?q=test" does and filter by the document's adult property?
Thanks in advance.
Your adult == true clause has to be part of the query - you can't pass in a term clause as a top level parameter to search.
So you could add it to the query as a query clause, in which case you need to join both query clauses using a bool query, as follows:
curl -XGET 'http://127.0.0.1:9200/_all/_search?pretty=1' -d '
{
"query" : {
"bool" : {
"must" : [
{
"query_string" : {
"query" : "test"
}
},
{
"term" : {
"adult" : true
}
}
]
}
},
"from" : 0,
"size" : 20
}
'
Really, though, query clauses should be used for:
full text search
clauses which affect the relevance score
However, your adult == true clause is not being used to change the relevance, and it doesn't involve full text search. It's more of a yes/no response, in other words it is better applied as a filter clause.
This means that you need to wrap your full text query (_all contains test) in a query clause which accepts both a query and a filter: the filtered query:
curl -XGET 'http://127.0.0.1:9200/_all/_search?pretty=1' -d '
{
"query" : {
"filtered" : {
"filter" : {
"term" : {
"adult" : true
}
},
"query" : {
"query_string" : {
"query" : "test"
}
}
}
},
"from" : 0,
"size" : 20
}
'
Filters are usually faster because:
they don't have to score documents, just include or exclude them
they can be cached and reused

Resources