ElasticSearch NEST - Search on multiple types but apply filter on selected Type alone - elasticsearch

I am looking to achieve a single query for search and filtering. But as expected when i applied filtering, the filter condition applied to all types so i got only the result of those document who have that filtered property and value .
For example,
Here i searched in 3 types (Product,Category,Manufacturer)
GET /my-index/Product,Category,Manufacturer/_search
{
"query": {
"filtered": {
"query": {...}, //--> Search a word which present in all types
"filter": {
"term": {
"ProductField": "VALUE"
}
}
}
}
}
Here i got only the result of Product type because Product type only contains field like 'ProductField' and has value as 'VALUE'.
What i am expecting is, with a single query, fetch all types results(Product,Category,Manufacturer), that satisfying the search query and apply filtering only on Product.
So my doubt is
Is there any way in Elastic search to apply filtering on specific type
search results alone than applying to all types?

Yes, you can use the type query to achieve exactly that. In the filter, we have a bool/should clause that selects either Category or Manufacturer without any other conditions, or Product documents having ProductField: VALUE:
POST /my-index/Product,Category,Manufacturer/_search
{
"query": {
"filtered": {
"query": {},
"filter": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"type": {
"value": "Category"
}
},
{
"type": {
"value": "Manufacturer"
}
},
{
"bool": {
"must": [
{
"type": {
"value": "Product"
}
},
{
"term": {
"ProductField": "VALUE"
}
}
]
}
}
]
}
}
}
}
}

Related

Elastic query combining should (boolean OR) with retrieval of nested documents

I have an Elastic index with nested documents. I am trying to retrieve multiple documents by ids along with their nested documents. Retrieving the documents themselves is simple enough with a Should query, but where and how would I include the nested doc query in this?
Boolean "Should" query:
GET myIndex/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"id": "123"
}
},
{
"term": {
"id": "456"
}
},
{
"term": {
"id": "789"
}
}
]
}
}
}
Query to retrieve nested docs:
"nested": {
"path": "myNestedDocs",
"query": {
"match_all": {}
}
It is not possible to add the nested query to each term query, because this gives a parsing exception: "[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]"
Also, it is not possible to add the nested doc query on the same level as the term queries, because then it would be treated as just another OR clause and simply retrieve all docs from the index.
Any ideas? Thanks!
As per my understanding, you want to match any one id from list and retrive nested document. If my understanding correct then You need to combined both the query to must clause like below:
{
"query": {
"bool": {
"must": [
{
"terms": {
"id": [
"123",
"456",
"789"
]
}
},
{
"nested": {
"path": "myNestedDocs",
"query": {
"match_all": {}
}
}
}
]
}
}
}

Elasticsearch search query: nested query with OR-gates & AND-gates

I have docs as follow:
{
"name": "...",
"country": "...",
}
I need to find. either one of the following criteria:
name=John AND country=US
name=Andy AND country=UK
How should be write this nested query?
Assuming the default fields mapping is defined, you can use boolean queries as follows:
{
"query": {
"bool": {
"should": [
{
"bool": {
"filter": [
{
"term": {
"name.keyword": "John"
}
},
{
"term": {
"country.keyword": "US"
}
}
]
}
},
{
"bool": {
"filter": [
{
"term": {
"name.keyword": "Andy"
}
},
{
"term": {
"country.keyword": "UK"
}
}
]
}
}
]
}
}
}
You should use must instead of filter if you want the query to contribute to the score.
must
The clause (query) must appear in matching documents and will
contribute to the score.
filter
The clause (query) must appear in matching documents. However unlike
must the score of the query will be ignored. Filter clauses are
executed in filter context, meaning that scoring is ignored and
clauses are considered for caching.

How to get documents that contain certain word in some fields with filtered query?

I want to find all books with "Agriculture" category. the books should contain word "paddy" in the title OR abstract field.
Here is my query :
GET /books/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"abstract": "paddy"
}
},
{
"match": {
"title": "paddy"
}
}
],
"filter": {
"term": {
"category": "Agriculture"
}
}
}
}
}
those query return all books with "Agriculture" category, even it's contain word "paddy" or not.
What did I do wrong?
Let me first explain to you how, Your query was fetching all the records, even it contains word "paddy" or not. This is b/c you are using the should clause which simply means that The clause (query) should appear in the matching document. but it means it is not forcing that it must appear, hence it's fetching all the documents in your index and then just filtering it on basis of category.
What you need is an upper level must clause, which means it must appear but then I used nested should as it can be either in title or abstract field, but at least one of these fields must contain the value, so that upper level must clause returns true.
The right query is below, which I tried locally and working fine, according to your use case:
{
"query": {
"bool": {
"must": {
"bool": {
"should": [
{
"match": {
"abstract": "paddy"
}
},
{
"match": {
"title": "paddy"
}
}
]
}
},
"filter": {
"term": {
"category": "agriculture"
}
}
}
}
}
Let me know if it's clear to you and solves your issue.

ElasticSearch Multi Match with Multiple Query Parameters

We have the following multi match query in Elastic Search
{
"query": {
"bool": {
"must": {
"multi_match": {
"query": "90803",
"type": "cross_fields",
"fields": [
"POSTAL_CODE^5",
"ADDRESS",
"CITY"
],
"operator": "and"
}
}
}
}}
How can we pass multiple query parameters. For e.g. we want to pass multiple ID in the query to match against the field Postal Code.
First, is POSTAL_CODE an analyzed field? If it's not the case you could use a Terms Query:
{
"query": {
"terms" : {
"POSTAL_CODE" : ["90803", "90809"]
}
}
}
If you want to use Match for some reason, there is not a Match Query that matches several values, you have to use a Bool Query with should or must depending on your use case.
Example with must:
{
"query": {
"bool": {
"must": [{
"match": { "POSTAL_CODE": "90803" }
}, {
"match": { "POSTAL_CODE": "90809" }
}]
}
}
}

Nested queries in Elastic search which should apply on all objects in nested array

Hi I have this document in ES with nested type:
{
"id": "92210f7f-b8a4-4d55-877d-8708154aa004",
"additionalData": {
"devices_nested": [
{
"version_string": "1"
},
{
"os_string": "Windows",
"version_string": "3"
},
{
"os_string": "Centos"
}
]
}
I want to do query that additionalData.devices_nested does not contain any element where os_string property does not exist that means I want to avoid such documents where some entries could have or not os_string property. Here is my query:
{
"query": {
"nested": {
"query": {
"bool": {
"must": {
"exists": {
"field": "additionalData.devices_nested.os_string"
}
}
}
},
"path": "additionalData.devices_nested"
}
}
}
But I always get the example document as result because at least one element satisfies query that there is os_string property.
Is it possible to make query which will return document where all elements in devices_nested has os_string property?
Is it possible to make query which will return document where all elements in devices_nested has os_string property?
Yes, it is posible. Instead of must exist, you have to use must_not missing approach.
In following query, the bool condition inside nested will match all documents that do not have os_string field in at least one of the nested objects, and then, the outside must_not query will exclude these documents. As a result, you'll get only documents that include os_string field in all nested objects:
{
"query": {
"bool": {
"must_not": {
"nested": {
"query": {
"bool": {
"must_not": {
"exists": {
"field": "additionalData.devices_nested.os_string"
}
}
}
},
"path": "additionalData.devices_nested"
}
}
}
}
}

Resources