Elasticsearch - Finding all entities with a nested id - node.js

I am trying to query a nested item but I am not sure how to formulate the query especially using javascript bodybuilder. Below is the mapping
I am trying to get all the active items (isActive: true) that have the "anomaly" id. I am not sure how to go about querying ElasticSearch.
In SQL I could just do something like a contains or having. I am using Node.js bodybuilder on the backend to query elasticsearch.

according to mapping,isActive and id are related to "anomalies" object. try this query
{
"query": {
"nested": {
"query": {
"bool": {
"filter": [
{
"match": {
"anomalies.isActive": {
"query": "true"
}
}
},
{
"match": {
"anomalies.id": {
"query": "any_value"
}
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"path": "anomalies",
"ignore_unmapped": false,
"score_mode": "none",
"boost": 1.0
}
}
}
}

Related

Elasticsearch search array inside elastic object

I am working on elastic search in node.js. I have 50k+ users in elstic search and now I have an of of phone numbers. Now I want to get those users from elastic search who match these number in array for this purpose I write search query string but this query give me exception I don't know where I am doing mistake in my query string.
Query String
{
"query": {
"bool": {
"must": [
{
"prefix": {
"phone":{"+9665509548","+93565822145",...}
}
}
]
}
}
}
Is this what you're after?
{
"query": {
"bool": {
"should": [
{
"prefix": {
"phone": "+9665509548"
}
},
{
"prefix": {
"phone": "+93565822145"
}
},
//...
],
"minimum_should_match": 1
}
}
}

Using NOT and OR together in Elastic search

This the query I used in elastic search to filter records that either satisfy one condition or does not satisfy other condition.
{
"query":
{
"query_string":
{
"query": "(NOT col1: \"val1\") OR (col2: val2)",
"analyze_wildcard": true
}}}
The problem is I am not able to write an equivalent syntax in nodejs to extract the information. We cant use must_not here as it is an OR condition
You will make both conditions in should array, as, if anyone matches you will get the record in results, you will have to use must match and must_not match
{
"query": {
"bool": {
"should": [
{
"bool": {
"must_not": {
"match": {
"col1": {
"query": "val1",
"type": "phrase"
}
}
}
}
},
{
"match": {
"col2": {
"query": "val2",
"type": "phrase"
}
}
}
]
}
}
}

How to sum two fields inside a bool Query in Elastic Search?

I am using Elasticsearch to find my result. How I sum two fields inside my query?
{
"query": {
"bool": {
"must": [
{ "term": { "x.flag1": "false" } },
{ "term": { "x.flag2": "false" } }
]
}
}
}
Now I want to find sum of two fields x.a and x.b and compare it with an other field, say x.c
(x.a + x.b === x.c)
I have to include this inside the bool query. So that only those records that satisfy both these conditions will be in my result. Is this possible?
You can do it via a script query like this:
The query for ES 2.x onwards:
{
"query": {
"bool": {
"must": [
{
"term": {
"x.flag1": "false"
}
},
{
"term": {
"x.flag2": "false"
}
}
],
"filter": {
"script": {
"script": "doc['x.a'].value + doc['x.b'].value === doc['x.c'].value"
}
}
}
}
}
The same query for a pre-2.0 ES version:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"x.flag1": "false"
}
},
{
"term": {
"x.flag2": "false"
}
},
{
"script": {
"script": "doc['x.a'].value + doc['x.b'].value === doc['x.c'].value"
}
}
]
}
}
}
}
}
Note that you need to enable dynamic scripting for this to work (i.e. script.inline: true).
However, if you have many documents, this can quickly slow down your ES cluster. If possible this should be done at indexing time, where you'd create another boolean field exactly for this purpose and then you can simply filter documents based on that boolean field which contains the true/false condition you need.

Division of two fields in Elasticsearch

Currently i am trying to group a field based on one field and than getting sum of other fields with respect to the respective field used for grouping. I want to get a new value which needs to be division of the summed field . I will provide the current query i have :
In my query i am aggregating them based on the field ("a_name") and summing "spend" and "gain". I want to get a new field which would be ratio of sum (spend/gain)
I tried adding script but i am getting NaN , also to enable this; i had to enable them first in elasticsearch.yml file
script.engine.groovy.inline.aggs: on
Query
GET /index1/table1/_search
{
"size": 0,
"query": {
"filtered": {
"query": {
"query_string": {
"query": "*",
"analyze_wildcard": true
}
},
"filter": {
"bool": {
"must": [
{
"term": {
"account_id": 29
}
}
],
"must_not": []
}
}
}
},
"aggs": {
"custom_name": {
"terms": {
"field": "a_name"
},
"aggs": {
"spe": {
"sum": {
"field": "spend"
}
},
"gained": {
"sum": {
"field": "gain"
}
},
"rati": {
"sum": {
"script": "doc['spend'].value/doc['gain'].value"
}
}
}
}
}
}
This particular query is showing me a 'NaN' in output. If I replace the division to multiplication the query works.
Essentially what i am looking for is to divide my two aggregators "spe" and "gained"
Thanks!
It might be possible that doc.gain is 0 in some of your documents. You may try changing the script to this instead:
"script": "doc['gain'].value != 0 ? doc['spend'].value / doc['gain'].value : 0"
UPDATE
If you want to compute the ratio of the result of two other metric aggregations, you can do so using a bucket_script aggregation (only available in ES 2.0, though).
{
...
"aggs": {
"custom_name": {
"terms": {
"field": "a_name"
},
"aggs": {
"spe": {
"sum": {
"field": "spend"
}
},
"gained": {
"sum": {
"field": "gain"
}
},
"bucket_script": {
"buckets_paths": {
"totalSpent": "spe",
"totalGained": "gained"
},
"script": "totalSpent / totalGained"
}
}
}
}
}

Boosting matched documents in Elasticsearch which have a certain tag

I have an index of documents that look this:
{
url: "/foo/bar",
html_blocks: [
"<h1>hi</h1>"
],
tags: [
"video",
"text"
],
title: "My title"
}
I'd like to query these documents on the title and html_blocks fields, and for any matches add a boost if they have a video tag.
So far, my query looks like this:
{
"query": {
"query_string": {
"query": "foo",
"fields": [
"title",
"html_blocks"
]
}
}
}
How do I modify it so that it continues to only return results if a match is found in the existing query, but a boost is added to any of the results which have a video tag? Thanks!
You want a custom_filters_score which will just boost on matches. Note that filter input is not analyzed, so you might wrap that in a query if you need it analyzed. Your other options to boost, while not really for this case are the boosting query, which is good for demoting results and the custom_score_query which is good for added boosts based on some calculated value.
See: Custom_filters_score
{
"query": {
"custom_filters_score": {
"query": {
"query_string": {
"query": "foo",
"fields": [
"title",
"html_blocks"
]
}
},
"filters": [
{
"filter": {
"term": {
"tags": "video"
}
},
"boost": 3
}
]
}
}
}
Edit:
This is what I mean by wrapping in a query using a filter query. Trust me, once you get the hang of ES, you'll be nested so knee deep that you'll produce some of the most satisfying queries ever.
{
"query": {
"custom_filters_score": {
"query": {
"query_string": {
"query": "foo",
"fields": [
"title",
"html_blocks"
]
}
},
"filters": [
{
"filter": {
//here comes the filter query, and I changed term to match
//since match analyzes
"query":{
"match": {
"tags": "video"
}
}
},
"boost": 3
}
]
}
}
}

Resources