How to use nested filters in Elasticsearch? - elasticsearch

I have a set of articles. I want to filter on tags AND host.
E.g I want all articles that are tagged with 'news' OR 'sport' AND has the 'host' set to 'cnn.com' OR 'bbc.com'.
I tried to create this nested bool filter, but that did not work. It also returns articles from other hosts.
Any suggestions?
GET _search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"should": [
// Match one or more of these tags.
{ "term" : { "tags" : "sport"} },
{ "term" : { "tags" : "news"} },
{ "bool": {
// Only from one of these hosts.
"should": [
{ "term": { "host": "bbc.com" } },
{ "term": { "host": "cnn.com" } }
]
}}
]
}
}
}
}
}

Nesting the query like this worked. :-)
GET _search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{ "bool": {
"should": [
{ "term" : { "tags" : "sport"} },
{ "term" : { "tags" : "news"} }
]
}},
{ "bool": {
"should": [
{ "term": { "host": "bbc.com" } },
{ "term": { "host": "cnn.com" } }
]
}}
]
}
}
}
}
}

Related

How can I put `must_not` under `filter` in Elasticsearch?

I'd like to use not equal in my filter but it doesn't work [13:24] [bool] failed to parse field [filter]:
"query": {
"bool": {
"filter": [
{
"must_not" : {
"term" : {
"status" : "DECLINED"
}
}
},
{
"term": { "type": "ORDER"}
}
]
}
}
it works if I put the must_not under query like below. How can I put not equal in filter?
"query": {
"bool": {
"must_not": {
"term": {
"status": "DECLINED"
}
},
"filter": ...
May be one more bool needed inside the filter ?
/_search
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"term": { "type": "ORDER"}
}
],
"must_not": [
{
"term": {
"status": "DECLINED"
}
}
]
}
}
}
}
}

Passing _type in Query parameter vs in URL in elastic search

I'm trying to query an elastic search cluster.
The index name is titles and _type is title. When I put the type in the request URL, the filtering works as expected:
POST http://esendpoint.com/titles/title/_search?
The body:
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{ "term" : {"_docTitleIds" : "65d-7ab2-41d4-a928-300accfc8ab7"}}
]
}
}
}
}
However if I add the _type title in the query body, and not in the URL I get all results under the index titles. But when used in the URL, I get results only from the type title
POST http://esendpoint.com/titles/_search
The body:
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{ "term" : {"_type" : "title"}},
{ "term" : {"_docTitleIds" : "65d-7ab2-41d4-a928-300accfc8ab7"}}
]
}
}
}
}
I'm not able to follow why this is happening.
You need to use filter (AND) instead of should (OR):
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"_type": "title"
}
},
{
"term": {
"_docTitleIds": "65d-7ab2-41d4-a928-300accfc8ab7"
}
}
]
}
}
}
}
}
The query below is for ES 2 and later:
{
"query": {
"bool": {
"filter": [
{
"term": {
"_type": "title"
}
},
{
"term": {
"_docTitleIds": "65d-7ab2-41d4-a928-300accfc8ab7"
}
}
]
}
}
}

Query regarding functionScoreQuery of elastic-builder npm for elasticsearch

I am using a functionScoreQuery provided by the elastic-builder npm to query my elasticsearch, query is getting created but i am not able to get outer query params for my query as shown below.
i.e the outer query params are missing and that is why the query does not execute so i had to manually append query { } in my body. So if anyone can help me out and tell me what i am missing in my npm query to get those query params.
var not_body = elasticbuilder.functionScoreQuery()
.query(elasticbuilder.matchAllQuery())
.functions([
elasticbuilder.weightScoreFunction()
.filter(elasticbuilder.boolQuery().mustNot([
elasticbuilder.hasChildQuery(
elasticbuilder.boolQuery().must([
elasticbuilder.matchPhraseQuery("name", "raju" )
])
).type('student')
]))
.weight(2),
elasticbuilder.weightScoreFunction()
.filter(elasticbuilder.boolQuery().must([
elasticbuilder.hasChildQuery(
elasticbuilder.boolQuery().must([
elasticbuilder.matchPhraseQuery("class", "12")
])
).type('info')
]))
.weight(2)
]).minScore(4).scoreMode('sum');
Current Output body via this query:
{
"function_score": {
"functions": [
{
"filter": {
"bool": {
"must_not": {
"has_child": {
"query": {
"bool": {
"must": {
"match_phrase": {
"name" : "raju"
}
}
}
},
"type": "student"
}
}
}
},
"weight": 2
},
{
"filter": {
"bool": {
"must": {
"has_child": {
"query": {
"bool": {
"must": {
"match_phrase": {
"class" : "12"
}
}
}
},
"type": "info"
}
}
}
},
"weight": 2
}
],
"query": {
"match_all": {}
},
"min_score": 4,
"score_mode": "sum"
}
}
Expected Output body:
{
"query": {
"function_score": {
"functions": [
{
"filter": {
"bool": {
"must_not": {
"has_child": {
"query": {
"bool": {
"must": {
"match_phrase": {
"name" : "raju"
}
}
}
},
"type": "student"
}
}
}
},
"weight": 2
},
{
"filter": {
"bool": {
"must": {
"has_child": {
"query": {
"bool": {
"must": {
"match_phrase": {
"class" : "12"
}
}
}
},
"type": "info"
}
}
}
},
"weight": 2
}
],
"query": {
"match_all": {}
},
"min_score": 4,
"score_mode": "sum"
}
}
}
You should wrap this in a elasticbuilder.requestBodySearch()
In your case
elasticbuilder.requestBodySearch().query(not_body)
should do the job

Elasticsearch use filter on index only when index has field

There are 2 indexes: categories, posts.
categories
name
body
posts
name
body
publish_at
publish_until
I want to do a query on both indexes with a filter on publish_at and publish_until for the posts index.
http://localhost:9200/categories,posts/_search
{
"query": {
"bool": {
"must": {
"multi_match": {
"query": "keyword",
"fields": [
"name^3",
"body"
]
}
},
"filter": [{
"bool": {
"must": [
{
"range": {
"publish_at": {
"lte" : "now"
}
}
},
{
"range": {
"publish_until": {
"gt" : "now"
}
}
}
]
}
}]
}
}
}
This query only gives me posts as results. I also want categories in my results.
How do I apply the date range filters to only indexes with publish_at and publish_until fields and skip the date range filters for the other indexes?
Ok after a day of fiddling with bool I got it working:
{
"query": {
"bool" : {
"must" : [
{
"multi_match": {
"query": "keyword",
"fields": [
"name^3",
"body"
]
}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"range": {
"publish_at": {
"lte" : "now"
}
}
},
{
"range": {
"publish_until": {
"gt" : "now"
}
}
}
]
}
},
{
"bool": {
"must_not": [
{
"exists": {
"field": "publish_at"
}
},
{
"exists": {
"field": "publish_until"
}
}
]
}
}
]
}
}
]
}
}
}

"boost" not working for "term" query

I'm running Elasticsearch 1.5.2 and trying the following query:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"gender": "male"
}
}
]
}
},
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"should": [
{
"term": {
"top_users": 1,
"boost": 2
}
}
]
}
}
}
}
}
Everything is fine until I add the "boost": 2 to the should -> term part. The complete query is much more complex, that's why I need to boost, but the remaining queries don't make any difference: ES returns an error 400 if a term query gets a boost argument:
QueryParsingException[[index_name] [_na] query malformed, must start with start_object]
Any suggestions?
It should be like this:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"gender": "male"
}
}
]
}
},
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"should": [
{
"term": {
"top_users": {
"value": "1",
"boost": 2
}
}
}
]
}
}
}
}
}

Resources