How to query documents where the query should have an and clause? - node.js

How do I use the nodejs driver for elastic search do achieve the following scenario. The scenario is that I have to update all documents in a "title" index where the tvSeries id is given and where the tvSeriesNumber is given?
I only want to match documents that fulfill both queries. I know that I should be using the client.updateByQuery method but I'm not sure what to put for the query body.

How about this? You probably need to modify the script in order to update whatever fields you want to.
client.updateByQuery({
index: "title",
type: "type",
body: {
"query": {
"bool": {
"filter": [
{ "term": { "tvSeriesId": 123} },
{ "term": { "tvSeriesNumber": 456} }
]
}
},
"script": {
"inline": "ctx._source.xyz = 'abc'"
}
}
}, function(err, res) {
if (err) {
reportError(err)
}
cb(err, res)
}
)

Related

How to filter data by field that contains specific string in ElasticSearch, Node Js?

I have simple Node Js application.
I want get filtered data by Path field, that contains 'get' word.
For example my data is like below:
"_source": {
"time": "2020-03-12T01:25:41.61836-07:00",
"level": "Info",
"info": {
"IpAddress": "0.0.0.0",
"Path": "/api/test/getTest/1",
"QueryString": "",
"UserAgent": "",
"LogDate": "2020-03-12T08:25:41.6220806Z",
"Username": "cavidan.aliyev",
"NodeId": "123456"
}
In other words my entity object's structure like as below:
{
time,
level,
info: {
IpAddress,
Path,
QueryString,
UserAgent,
LogDate,
Username,
NodeId
}
}
My query is like below:
client.search({
index: collectionName,
body: {
from: (params.currentPage - 1) * params.pageSize,
size: params.pageSize,
"query": {
"bool": {
"must": mustArr,
"filter": [
{
"match_all": {}
}
]
}
}
}
}, function (err, res) {
if (err) {
reject(err);
}
else {
let result = res.hits.hits. map(x => x._source);
resolve(result);
}
});
How I can filter data by Path field, that contains 'get' word?
Please help me, thanks
You can make use of Wildcard Query inside the filter query you have. I'm assuming that you are making use of Standard Analyzer for info.Path field.
Note that for the sake of simplicity I've just mentioned what should be going inside the filter query you have.
If info.Path is nested type:
POST <your_index_name>/_search
{
"query": {
"bool": {
"filter": { <--- Note this
"nested": {
"path": "info",
"query": {
"wildcard": {
"info.Path": {
"value": "*get*"
}
}
}
}
}
}
}
}
If info.Path is object type:
POST <your_index_name>/_search
{
"query": {
"bool": {
"filter": { <--- Note this
"wildcard":{
"info.Path": "*get*"
}
}
}
}
}
Important Note: Wildcard search slows the query performance, and if you have a control on the Elasticsearch's index, then you should definitely look at ngram search model, which creates n-gram tokens at index-time as mentioned in this link.
Let me know if this helps!
If you don't want returned data with "get" keywords, your wildcard should type into the must_not.
For example:
POST <your_index_name>/_search
{
"query": {
"bool": {
"must_not":{
"filter": {
"wildcard":{
"info.Path": "*get*"
}
}
}
}
}
}

Getting data from elasticsearch when field is undefined or missing from object

I'm trying to get data from elastic search by querying some field which indicates if the object was already handled. let's call it 'isHandled".
There are some objects that indexed without this field.
Is there any way to get the data that "isHandled" is just not "true" (false or even missing)?
Thanks
You can use the exists query to achieve that. This query will return you all documents where isHandled is either false or not existing.
{
"query": {
"bool": {
"should": [
{
"term": {
"isHandled": "false"
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "isHandled"
}
}
}
}
]
}
}
}

How to use client.updateByQuery elasticsearch library for nodejs? [duplicate]

You have an Elasticsearch index with two docs:
[
{
"_index": "myIndex",
"_type": "myType",
"_id": "es1472002807930",
"_source": {
"animal": "turtle",
"color": "green",
"weight": 20,
}
},
{
"_index": "myIndex",
"_type": "myType",
"_id": "es1472002809463",
"_source": {
"animal": "bear",
"color": "brown"
"weight": 400,
}
}
]
Later, you get this updated data about the bear:
{
"color": "pink",
"weight": 500,
"diet": "omnivore",
}
So, you want to update the "color" and "weight" values of the bear, and add the "diet" key to the "bear" doc. You know there's only one doc with "animal": "bear" (but you don't know the _id):
Using the Nodejs driver, what updateByQuery syntax would update the "bear" doc with these new values?
(NOTE: this question has been entirely edited to be more useful to the SO community!)
The answer was provided by Val in this other SO:
How to update a document based on query using elasticsearch-js (or other means)?
Here is the answer:
var theScript = {
"inline": "ctx._source.color = 'pink'; ctx._source.weight = 500; ctx._source.diet = 'omnivore';"
}
client.updateByQuery({
index: myindex,
type: mytype,
body: {
"query": { "match": { "animal": "bear" } },
"script": theScript
}
}, function(err, res) {
if (err) {
reportError(err)
}
cb(err, res)
}
)
The other answer is missing the point since it doesn't have any script to carry out the update.
You need to do it like this:
POST /myIndex/myType/_update_by_query
{
"query": {
"term": {
"animal": "bear"
}
},
"script": "ctx._source.color = 'green'"
}
Important notes:
you need to make sure to enable dynamic scripting in order for this to work.
if you are using ES 2.3 or later, then the update-by-query feature is built-in
if you are using ES 1.7.x or a former release you need to install the update-by-query plugin
if you are using anything between ES 2.0 and 2.2, then you don't have any way to do this in one shot, you need to do it in two operations.
UPDATE
Your node.js code should look like this, you're missing the body parameter:
client.updateByQuery({
index: index,
type: type,
body: {
"query": { "match": { "animal": "bear" } },
"script": { "inline": "ctx._source.color = 'pink'"}
}
}, function(err, res) {
if (err) {
reportError(err)
}
cb(err, res)
}
)
For elasticsearch 7.4 you could use
await client.updateByQuery({
index: "indexName",
body: {
query: {
match: { fieldName: "valueSearched" }
},
script: {
source: "ctx._source.fieldName = params.newValue",
lang: 'painless',
params: {
newValue: "newValue"
}
}
}
});

How do you pass arguments to elasticsearch inline scripts using the nodejs driver?

The situation I want to solve is to update documents in a titles index with titles matching certain parameters using the nodejs driver for elasticsearch. The current query I'm using is this
client.updateByQuery({
index: "title",
type: "type",
body: {
"query": {
"bool": {
"filter": [
{ "term": { "tvSeriesId": 123} },
{ "term": { "tvSeriesNumber": 456} }
]
}
},
"script": {
"inline": "ctx._source.someRandomField = 'abc'"
}
}
}, function(err, res) {
if (err) {
reportError(err)
}
cb(err, res)
}
)
I want the script to be dynamic where I can pass a value to the script to change the value of a field. For example, the value of someRandomField could be declared in a previous variable before the query call. How can i pass that variable to the script?
You can use the script params to do this:
client.updateByQuery({
index: "title",
type: "type",
body: {
"query": {
"bool": {
"filter": [
{ "term": { "tvSeriesId": 123} },
{ "term": { "tvSeriesNumber": 456} }
]
}
},
"script": {
"inline": "ctx._source.someRandomField = newValue"
"params": {
"newValue": newRandomFieldValue
}
}
}
}, function(err, res) {
if (err) {
reportError(err)
}
cb(err, res)
}
)
newRandomFieldValue would be a variable in your Node.js code that is then used as a script parameter.

Elastic search search query with Filter

Am new to elastic search, this is my query to find a exact match in my collection.
{
"query": {
"filtered": {
"query": {
"match": {
"_id": {
"query": "1"
}
}
},
"filter": {
"term" : {
"team_id":"2",
"created_user":"099"
}
}
}
}
}
By running this query I am getting one record, but my problem is its not matching "team_id" filed. When I change team_id to some other value eg: 4, I am still getting the record with team_id = 2, Please help me to write an elastic search query with three fields. Thanks
If you want exact match, be sure that fields that you want to make search operation must be not_analyzed. And it seems you are using multiple case in your filter. You can refactor your query by using and filter like;
{
"query": {
"filtered": {
"query": {
"match": {
"_id": {
"query": "1" // remember that, this will always return one result. Update here according to your needs. For example, use tag instead of _id like tag=responsive in order to get results that matches tag field with responsive
}
}
},
"filter": {
"and": [
{
"term": {"team_id":"2"}
},
{
"term": {"created_user":"099"}
}
]
}
}
}

Resources