ElasticSearch - Single match to multiple - elasticsearch

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.

Related

ElasticSearch filtered bool query not working with multi_match

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"}
}
]
}
}
}

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
}
}
}
}

Elastic Search Nested Object mapping and Query for search

I am trying to use Elastic Search and I am stuck trying to query for the nested object.
Basically my object is of the following format
{
"name" : "Some Name",
"field2": [
{
"prop1": "val1",
"prop2": "val2"
},
{
"prop1": "val3",
"prop2":: "val4"
}
]
}
Mapping I used for the nested field is the following.
PUT /someval/posts/_mapping
{
"posts": {
"properties": {
"field2": {
"type": "nested"
}
}
}
}
Say now i insert elements for /field/posts/1 and /field/posts/2 etc. I have k values for field2.prop1 and i want a query which gets the posts sorted based on most match of field2.prop1 among the K values i have. What would be the appropriate query for that.
Also I tried a simple filter but even that doesnt seem to work right.
GET /someval/posts/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
}
},
"filter" : {
"nested" : {
"path" : "field2",
"filter" : {
"bool" : {
"must" : [
{
"term" : {"field2.prop1" : "val1"}
}
]
}
},
"_cache" : true
}
}
}
}
The above query should match atleast the first post. But it returns no match. Can anyone help to clarify whats wrong here ?
There was problem in your json structure, you used filtered query , but filter(object) was in different level than query.
Find the difference.
POST /someval/posts/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "field2",
"filter": {
"bool": {
"must": [
{
"term": {
"field2.prop1": "val1"
}
}
]
}
},
"_cache": true
}
}
}
}
}

How to add filter to a more like this query in Elastic Search?

I want to use a More like this query in Elastic Search to find similar documents. However I need to filter the documents on which the query is executed.
Example below: I want to find blog items that are similar to blog with id 123456, but written by author 120 or author 123.
When executing this query, I get back similar blogs from ALL authors and thus not filtered ...
{
"query":{
"more_like_this" : {
"fields" : ["body" ],
"docs" : [
{
"_id" : "123456"
}
],
"percent_terms_to_match" : 0.4,
"min_term_freq" : 1
}
}
},
"filter":{
"and":[
{
"type":{ "value":"blog" }
},
{
"terms":{ "authorId": ["120", "123"] }
}
]
}
}
Try filtered query like this:
{
"query": {
"filtered": {
"query": {
"more_like_this": {
"fields": [
"body"
],
"docs": [
{
"_id": "123456"
}
],
"percent_terms_to_match": 0.4,
"min_term_freq": 1
}
},
"filter": {
"and": [
{
"type": {
"value": "blog"
}
},
{
"terms": {
"authorId": [
"120",
"123"
]
}
}
]
}
}
}
}
Hope it helps...!
The accepted answer is for earlier versions of ElasticSearch. This one works great on 2.x+ also not using any depreciated APIs
{
"query": {
"filtered": {
"query": {
"more_like_this": {
"fields": ["meta.keywords"],
"like": [{"_id": "5732759249d2b21f95641d50"}]
}
},
"filter" : {
"bool": {
"must": [
{"match": { "foo.bar": "A"}},
{"match": { "baz": "new"}}
]
}
}
}
}
}

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