ElasticSearch filtered bool query not working with multi_match - elasticsearch

I have this installed on Ubuntu running ElasticSearch 6.2.3
I am new to ES so if this is duplicate or obvious I am sorry.
I just need to do a contains query that filters out items not marked as PUBLISHED.
Here is what i think should be returning the correct results but it returns nothing (0 hits):
GET /index/type/_search
{
"query": {
"bool" : {
"must" : {
"multi_match" : {
"query": "Funny black cat",
"operator": "and",
"fields": [ "title", "description"]
}
},
"filter": {
"term" : { "publishStatus" : "PUBLISHED" }
}
}
}
}
Furthermore, this simple filter query is also return 0 records...
GET /index/type/_search
{
"query": {
"bool": {
"filter": {
"term": {
"publishStatus": "PUBLISHED"
}
}
}
}
}

Well this is what worked for me (stopped using filter, changed to match):
GET index/type/_search
{
"query": {
"bool":{
"must":[
{
"multi_match" : {
"query": "dinner sydney",
"fields": [ "title^3", "description" ],
"operator": "and"
}
},{
"match": { "publishStatus": "PUBLISHED"}
}
]
}
}
}

Related

Elasticsearch: Minimum_should_match don´t return correctly

I'm new to the elastic universe and I have a question about a query. I'll try to describe it here:
I have a document called 'store' with several stores registered and within each store item a list of customers:
loja {
nome,
telefone,
email,
clientes : [
{
nomeCliente,
telefone,
email
}
]
}
I need a query where I would have to return at least 1 pair of customers from the same registered store
For example:
I research 'Ana Maria', 'Sandra Maria' and 'Alberto Braz', where I would need to return the stores that have [Ana Maria and Sandra Maria] or [Ana Maria and Alberto Braz] or [Sandra Maria and Alberto Braz].
I did the search according to the dsl below, but the minimum_should_match clause is not respecting the limit of 2 m and returning results with only 1 record found.
Am I doing something wrong in the query?
Could you help me out on this one?
Query:
{
"query": {
"bool": {
"must": [
{
"nested": {
"query": {
"bool":{
"should": {
"match": {
"clientes.nomeCliente" : {
"query" : "ANA MARIA",
"type" : "phrase",
"operator": "and",
"slop" : 40
}
}
},
"should": {
"match":{
"clientes.nomeCliente" : {
"query" : "SANDRA MARIA",
"type" : "phrase",
"operator": "and",
"slop" : 40
}
}
},
"should": {
"match":{
"clientes.nomeCliente" : {
"query" : "ALBERTO BRAZ",
"type" : "phrase",
"operator": "and",
"slop" : 40
}
}
}
},"minimum_should_match": 2
},
"path": "clientes",
"inner_hits" : {
"size" : 10
}
}
}
]
}
}
}
For the should you need to use an array instead of an object. So, you query need to be something like this :
{
"query": {
"bool": {
"must": [
{
"nested": {
"query": {
"bool": {
"should": [
{
"match": {
"clientes.nomeCliente": {
"query": "ANA MARIA",
"type": "phrase",
"operator": "and",
"slop": 40
}
}
},
{
"match": {
"clientes.nomeCliente": {
"query": "SANDRA MARIA",
"type": "phrase",
"operator": "and",
"slop": 40
}
}
},
{
"match": {
"clientes.nomeCliente": {
"query": "ALBERTO BRAZ",
"type": "phrase",
"operator": "and",
"slop": 40
}
}
}
],
"minimum_should_match": 2
}
},
"path": "clientes",
"inner_hits": {
"size": 10
}
}
}
]
}
}
}
I could not check the parameters of the match query because I don't have the mapping and sample data. But you can check that part with your index directly.

nested boolean with match query in elasticsearch

I would like to match within a boolean query in Elasticsearch. I have the match query and boolean query working as expected now, but I am not sure how to have a AND to combine them.
nested boolean
{
"query": {
"constant_score" : {
"filter":{
"bool":{
"must":[
{"terms":{"address.keyword": addr}},
{"bool":{
"should":[
{"terms": {"state.keyword": state}}
,{"terms": {"city.keyword": city}}
]
}}
]
}
}
}}}
match
{"query": {
"match": {
"auct_title": {
"query": keyword,
"operator": "and"
}
}
}
, "collapse" : {
"field" : "id"
}
,"sort" : [
{ sort_field: {"order" : sort_order} }]
,"size":20
}
You can move natch to the must clause . So document has to satisfy three conditions
1.address
2.either of state/city
2.match on auct_title
It will then return one document per Id based on sort order passed
GET <index>/_search
{
"query": {
"constant_score": {
"filter": {
"bool": {
"must": [
{
"term": {
"address.keyword": "addr"
}
},
{
"bool": {
"should": [
{
"term": {
"state.keyword": "state"
}
},
{
"term": {
"city.keyword": "city"
}
}
]
}
},
{
"match": {
"auct_title": {
"query": "keyword",
"operator": "and"
}
}
}
]
}
}
}
},
"collapse": {
"field": "id"
},
"sort": [
{
"FIELD": {
"order": "desc"
}
}
],
"size": 20
}

ElasticSearch - Single match to multiple

Note that I am a complete newbie with ElasticSearch and I'm on a time crunch. I've got the query below:
{
    "query": {
        "filtered": {
            "query": {
                "match": {
                    "state": "VA"
                }
            },
            "filter": {
                "and": [
                    {
                        "bool": {
                            "must": [
                                {
                                    "match": {
                                        "status": "Active"
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    },
    "sort": [
        "dom"
    ],
    "size": 1
}
At the moment, the codebase only supports searching for items with one state in particular. I am trying to modify it to support a list of possible state values. Now, I've seen where one can use should and terms but the results for both are empty data sets.
I've tried looking this up but examples I've seen either don't work, or have very poorly explained (if at all) solutions, or depend on reading and absorbing pages of documentation (for which I simply do not have the time). How would I modify the top query to search for multiple values?
Update
Running the following:
curl -XGET localhost:9200/listings/_mapping/listing/field/state?pretty
I have acquired this mapping:
{
"listings" : {
"mappings" : {
"listing" : {
"state" : {
"full_name" : "state",
"mapping" : {
"state" : {
"type" : "string"
}
}
}
}
}
}
}
Update 2
I've updated the mapping to set it to not_analyzed and enabled the store option. Data has been reimported. The new request looks like this:
{
"query":{
"filtered":{
"filter":{
"and":[
{
"bool":{
"should":[
{
"terms":{
"state":["VA","MD"]
}
}
]
}
},{
"bool":{
"must":[
{
"match":{
"status":"Active"
}
}
]
}
}
]
}
}
},
"sort":["dom"],
"size":1
}
Did you try replacing the inner "query" for your "reverse engineered" query?
Something like this:
{
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{
"match": {
"state": "VA"
}
},
{
"match": {
"state": "MD"
}
}
]
}
},
"filter": {
"and": [
{
"bool": {
"must": [
{
"match": {
"status": "Active"
}
}
]
}
}
]
}
}
},
"sort": [
"dom"
],
"size": 1
}
By the way, this query is a bit messy. You could reestrucuture it combining the "must" and "should" clauses under a single "bool". You could then discard the "filtered" query and use the single "bool" immediately under root "query" tag, or discard "query" section of "filtered" and use only the "filter" part.

Must not query elasticsearch

I have my request:
{
"size": 10,
"query": {
"filtered": {
"query": {
"bool": {
"must": [
{"term": {"event": "matchmaking_done"}}
]
}
},
"filter": {
"range": {
"#timestamp": {
"gt" : "2016-06-01T00:00:00.000Z",
"lte" : "2016-06-01T00:05:00.000Z"
}
}
}
}
},
"aggs" : {
"user-ids" : {
"terms" : { "field" : "user_id",
"size": 0
}
}
}
}
And I need to add into this request parameter - does not contain field pvp_league! I tried add must_not but can't understand how to do this correct.
Help please!
You answered it yourself, but the ES 2.x way to do this is to not use the filtered query because it has been deprecated and it will be removed in ES 5.0. ES 2.x introduces the concept of the "filter" context rather than every query being either just a query or a filter; now every query is both a filter or a query (scored), just depending on the context it's used in.
For your query, this therefore becomes a little simpler because of the simplified bool / filter syntax:
{
"size":10,
"query":{
"bool":{
"must":[
{
"term":{
"event":"matchmaking_done"
}
}
],
"must_not":[
{
"exists":{
"field":"pvp_league"
}
}
],
"filter":[
{
"range":{
"#timestamp":{
"gt":"2016-06-01T00:00:00.000Z",
"lte":"2016-06-01T00:05:00.000Z"
}
}
}
]
}
},
"aggs":{
"user-ids":{
"terms":{
"field":"user_id",
"size":0
}
}
}
}
As a very big aside, specifying "size" : 0 for the terms aggregation, you are requesting all unique terms, up to INT_MAX. That is not a scalable request (works great with 10 user_ids, or even 100, but not 10000 users).
As a not-so-bad aside, your request doesn't need a query context at all because nothing about the search side of it cares about relevance. Your term query ("event" : "matchmaking_done") either matches or it doesn't. Since you either want it to match or not, but you don't really care about order inherently, you should use this in the filter context. This changes the request to:
{
"size": 10,
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "pvp_league"
}
}
],
"filter":[
{
"range": {
"#timestamp": {
"gt":"2016-06-01T00:00:00.000Z",
"lte":"2016-06-01T00:05:00.000Z"
}
}
},
{
"term": {
"event": "matchmaking_done"
}
}
]
}
},
"aggs": {
"user-ids": {
"terms": {
"field": "user_id",
"size": 0
}
}
}
}
I've found solution! It looks like this:
{
"size": 10,
"query": {
"filtered": {
"query": {
"bool": {
"must": [
{"term": {"event": "matchmaking_done"}}
],
"must_not": [
{"filtered": {
"filter": {
"exists": {
"field": "pvp_league"
}
}
}
}
]
}
},
"filter": {
"range": {
"#timestamp": {
"gt" : "2016-06-01T00:00:00.000Z",
"lte" : "2016-06-01T00:05:00.000Z"
}
}
}
}
},
"aggs" : {
"user-ids" : {
"terms" : { "field" : "user_id",
"size": 0
}
}
}
}

Elasticsearch multi term filter

I'm quite new to Elasticsearch, so here's my question.
I wanna do a search query with elasticsearch and wanna filter with multiple terms.
If I want to search for a user 'tom', then I would like to have all the matches where the user 'isActive = 1', 'isPrivate = 0' and 'isOwner = 1'.
Here's my search query
"query":{
"filtered": {
"query": {
"query_string": {
"query":"*tom*",
"default_operator": "OR",
"fields": ["username"]
}
},
"filter": {
"term": {
"isActive": "1",
"isPrivate": "0",
"isOwner": "1"
}
}
}
}
When I use 2 terms, it works like a charm, but when i use 3 terms it doesn't.
Thanks for the help!!
You should use bool filter to AND all your terms:
"query":{
"filtered": {
"query": {
"query_string": {
"query":"*tom*",
"default_operator": "OR",
"fields": ["username"]
}
},
"filter": {
"bool" : {
"must" : [
{"term" : { "isActive" : "1" } },
{"term" : { "isPrivate" : "0" } },
{"term" : { "isOwner" : "1" } }
]
}
}
}
}
For version 2.x+ you can use bool query instead of filtered query with some simple replacement: https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-filtered-query.html
As one of the comments says, the syntax has changed in recent ES versions. If you are using Elasticsearch 6.+, and you want to use a wildcard and a sequence of terms in your query (such as in the question), you can use something like this:
GET your_index/_search
{
"query": {
"bool": {
"must": [
{
"wildcard": {
"your_field_name_1": {
"value": "tom*"
}
}
},
{
"term": {
"your_field_name_2": {
"value": "US"
}
}
},
{
"term": {
"your_field_name_3": {
"value": "Michigan"
}
}
},
{
"term": {
"your_field_name_4": {
"value": "0"
}
}
}
]
}
}
}
Also, from the documentation about wildcard queries:
Note that this query can be slow, as it needs to iterate over many
terms. In order to prevent extremely slow wildcard queries, a wildcard
term should not start with one of the wildcards * or ?.
I hope this helps.

Resources