Filter documents where all values of an array meet some criteria in elasticsearch - elasticsearch

I have documents that look like this:
{
times: [{start: "1461116454242"},{start:"1461116454242"}]
}
I want to get all documents where every start time is in the past. This query works when all times are in the future or all are in the past, but fails if only one time is in the future (still matches).
query: {
filtered: {
filter: {
bool: {
must: [
{
nested: {
path: "times",
filter: {
script : {
script: "doc['start'].value < now",
params: {
now: Date.now()
}
}
}
}
}
]
}
},
query: {
match_all: {}
}
}
}

One solution that I just realized:
query: {
filtered: {
filter: {
bool: {
must: [
{
nested: {
path: "times",
filter: {
"bool": {
"must": [
{
"range": {
"times.start": {
lt: new Date()
}
}
}
]
}
}
}
}
],
must_not: [
{
nested: {
path: "times",
filter: {
"bool": {
"must": [
{
"range": {
"times.start": {
gte: new Date()
}
}
}
]
}
}
}
}
]
}
},
query: {
match_all: {}
}
}
}

How about this one:
include_in_parent: true in your mapping:
"times": {
"type": "nested",
"include_in_parent": true,
"properties": {
"start": {
"type": "date"
}
}
}
and use the query_string syntax, without nested:
{
"query": {
"query": {
"query_string": {
"query": "times.start:<=now AND NOT times.start:>now"
}
}
}
}

Related

Elasticsearch '[bool] failed to parse field [filter]' exception

I am trying to solve parsing exception of my search query.
I would like to get some help there :)
The exception reason:
'[1:65] [bool] failed to parse field [filter]'
message:'x_content_parse_exception'
My search:
data = (await this.elasticClient.search({
index: Indexes.Measurements,
size: 10000,
body: {
query: {
bool: {
filter: {
terms: {
"MachineId": ["mo3", "mo2"]
},
range: {
'#timestamp': {
gte: `now-${lastMinutes}m`,
lte: 'now'
}
}
}
},
},
sort : [{ "#timestamp" : "desc" }]
}})).body.hits.hits.map(data => data._source);
You are missing [] around the filter clause, try out this below query
data = (await this.elasticClient.search({
index: Indexes.Measurements,
size: 10000,
body: {
query: {
bool: {
filter: [{
terms: {
"MachineId": ["mo3", "mo2"]
}},{
range: {
'#timestamp': {
gte: `now-${lastMinutes}m`,
lte: 'now'
}
}}]
}
},
},
sort : [{ "#timestamp" : "desc" }]
}})).body.hits.hits.map(data => data._source);
In JSON format, it will be like this
{
"query": {
"bool": {
"filter": [
{
"terms": {
"MachineId": [
"mo3",
"mo2"
]
}
},
{
"range": {
"timestamp": {
"gte": "now-${lastMinutes}m",
"lte": "now"
}
}
}
]
}
}
}

Handling Optional field search in Elasticsearch

I'm using ES 5.5 and having a query dsl with javasript API request like this
client.search({
index: 'demo',
type: 'sample',
body: {
"query": {
"bool": {
"must": [
{
"match": {
"CityName": {
query: req.params.city,
slop: 100
}
}
},
{
"match": {
"StateName": {
query: req.params.state,
slop: 100
}
},
{
"match": {
"Code": {
query: req.params.code,
slop: 100
}
}
}
]
}
}
}
})
This query works fine when user gives all three values.But In my case these three parameters are not mandatory.Either user can give one value or more than one value and given fields must match the documents.Searching with one or two values doesn't return anything.
You need to replace the must with should. refer boolean query for more details
client.search({
index: 'demo',
type: 'sample',
body: {
"query": {
"bool": {
"must": [ --> replace this `must` with `should`
{
"match": {
"CityName": {
query: req.params.city,
slop: 100
}
}
},
{
"match": {
"StateName": {
query: req.params.state,
slop: 100
}
},
{
"match": {
"Code": {
query: req.params.code,
slop: 100
}
}
}
]
}
}
}
})

ElasticSearch filter by nested boolean type fields

I need to query on multiple nested fields on boolean types.
Structure of mapping:
"mappings" : {
"properties" : {
"leaders" : {
"type" : "nested",
"properties" : {
"except_1" : {
"type" : "boolean"
},
"except_2" : {
"type" : "boolean"
},
"counter" : {
"type" : "integer"
}
}
}
}
}
I am trying to use query both except1 and except2 only to False.
Below my try, unfortunately it returns True and False for both fields and I cannot fix it.
"query": {
"nested": {
"path": "leaders",
"query": {
"bool": {
"must": [
{
"term": {
"leaders.except_1": False
}
},
{
"term": {
"leaders.except_2": False
}
}
]
}
}
}
}
What you're probably looking for is the inner_hits option -- showing only the matched nested subdocuments.
PUT leaders
{"mappings":{"properties":{"leaders":{"type":"nested","properties":{"except_1":{"type":"boolean"},"except_2":{"type":"boolean"},"counter":{"type":"integer"}}}}}}
POST leaders/_doc
{
"leaders": [
{
"except_1": true,
"except_2": false
},
{
"except_1": false,
"except_2": false
}
]
}
GET leaders/_search
{
"query": {
"nested": {
"path": "leaders",
"inner_hits": {},
"query": {
"bool": {
"must": [
{
"term": {
"leaders.except_1": false
}
},
{
"term": {
"leaders.except_2": false
}
}
]
}
}
}
}
}
then
GET leaders/_search
{
"query": {
"nested": {
"path": "leaders",
"inner_hits": {},
"query": {
"bool": {
"must": [
{
"term": {
"leaders.except_1": false
}
},
{
"term": {
"leaders.except_2": false
}
}
]
}
}
}
}
}
yielding
{
"hits":[
{
"_index":"leaders",
"_type":"_doc",
"_id":"u-he8HEBG_KW3EFn-gMz",
"_score":0.87546873,
"_source":{ <-- default behavior
"leaders":[
{
"except_1":true,
"except_2":false
},
{
"except_1":false,
"except_2":false
}
]
},
"inner_hits":{
"leaders":{
"hits":{
"total":{
"value":1,
"relation":"eq"
},
"max_score":0.87546873,
"hits":[ <------- only the matching nested subdocument
{
"_index":"leaders",
"_type":"_doc",
"_id":"u-he8HEBG_KW3EFn-gMz",
"_nested":{
"field":"leaders",
"offset":1
},
"_score":0.87546873,
"_source":{
"except_1":false,
"except_2":false
}
}
]
}
}
}
}
]
}
Furthermore, you can force the system to only return the inner_hits by saying "_source": "inner_hits" on the top-level of your search query.

Elasticsearch conditional filter

I need to filter out documents with some kind of conditional logic (I think), but I can't get this working.
My documents are like this:
{type: 'A'}
{type: 'B', foo: ['bar']}
{type: 'B', foo: []}
Now I need to filter out all documents of type 'B' where foo is empty.
In pseudocode the query would be:
if(type == 'B' && foo == []) {
// filter out this document
}
My main query looks like this:
query: {
filtered: {
query: {
bool: {
must: {
match_all: []
}
}
},
filter: {
bool:{
must_not: {
term: {'_hidden': true}
}
}
}
}
}
Elasticsearch Version is 1.5.0
If I understood, is that?
if type == a, all documents that have a will return.
And if type == b and the field foo is not there they will return, make sense?
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"should": [
{
"term": {
"type": "a"
}
},
{
"bool": {
"must": [
{
"term": {
"type": "b"
}
}
],
"must_not": [
{
"missing": {
"field": "foo"
}
}
]
}
}
]
}
}
}
}
}

Elasticsearch: wildcard in query differences : "Alex*" vs "*lex*"

I have a bunch of data indexed using keyword tokenizer.
{
state: open
settings: {
index.number_of_replicas: 0
index.analysis.analyzer.default.type: keyword
index.number_of_shards: 5
index.version.created: 900599
}
mappings: {
evenements: {
properties: {
prenom: {
type: string
}
nom: {
type: string
}
statut: {
type: string
}
fieldDate: {
format: dateOptionalTime
type: date
}
}
}
}
}
When querying
{
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "evenements.prenom",
"query": "*lex*"
}
}
]
}
}
}
I get results, but when querying
{
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "evenements.prenom",
"query": "Alex*"
}
}
]
}
}
}
I get no results (A ou a instead of first * does not change anything).
Any explanation about this ?
Thanks.
Yann
Try to set lowercase_expanded_terms property of query string to false. By default this property is set to true and can cause the behaviour you are having.
{
"query": {
"bool": {
"must": [
{
"query_string": {
"lowercase_expanded_terms": false,
"default_field": "evenements.prenom",
"query": "Alex*"
}
}
]
}
}
}

Resources