Conversion of SQL Update clause into ElasticSearch Update - sql

I would like to do the following update query on my ES index called "avails-ingest-history". How would I do the below in ES?
UPDATE `avails-ingest-history`
SET is_hidden = False
WHERE transaction_guid='XXX'
Here is what I have so far:
body = {
"script": {
"is_hidden": False
},
"query": {
"match": {
"guid": "xxx"
}
}
}
However, I wasn't sure about the script key or whether an exact match uses the match term.

I'm not sure if this is the preferred way to do the above, but here is the way that I'm currently using:
body = {
"script": {
"lang": "painless",
"inline": "ctx._source.is_hidden=false"
},
"query": {
"match": {
"guid": "xxx"
}
}
}
self.es.update_by_query(body=body, doc_type='_doc', index='avails-ingest-history')
I am open to better ways to accomplish the above.

Related

How to check a particular value in karate on basis of condition when there are more than one key in response

There are multiple keys present in x.details[0].user so how to compare in such condition. It works fine where there is only one key while when there are more than one key it fails with error as there are multiple keys for user.
Please guide
* def array =
"""
{
"type": "1",
"array": 2,
"details": [
{
"path": "path",
"user": {
"school": {
"name": [
{
"value": "this is school",
"codeable": {
"details": [
{
"hello": "yty",
"condition": "check1"
}
],
"text": "123S"
}
}
]
},
"sample": "test1",
"id": "22222"
},
"data": {
"check": "abc"
}
},
{
"path": "path",
"user": {
"school": {
"name": [
{
"value": "this is school",
"codeable": {
"details": [
{
"hello": "def",
"condition": "check2"
}
],
"text": "123O"
}
}
]
},
"sample": "test",
"id": "11111"
},
"data": {
"check": "xyz"
}
}
]
}
"""
* def lookup = { 'check1': 'yty', 'check2': 'def' }
* match each array.details contains { user: { school: { name[0]: { codeable: { details[0]: { hello: '#(lookup[_$.user.school.name[0].codeable.details[0].condition])' } } } } } }
I have tried multiple ways but not sure how to make it work when there are more than one keys getting returned.
First let me say this. Please, please do not try to be "too clever" in your tests. Read this please: https://stackoverflow.com/a/54126724/143475
Just have simple tests that test for specific, predictable responses and stop there. The maximum complexity should be match contains, that's it. What you are trying to do is in my opinion a waste of time, and will just cause grief for anyone who tries to maintain these tests in future.
That said, I'm giving you a completely different approach here. There are a few different ways, this is just one. Here we attack the problem piece by piece instead of trying to write one massive match.
* def allXyz = array.details.filter(x => x.data.check == 'xyz')
* match each allXyz..details == [{ hello: 'def', condition: 'check2' }]
You should be able to extend this to do all the weird assertions that you want. If you are wondering what allXyz..details does, you can print it like this:
* def temp = $allXyz..details
* print temp

Elasticsearch Not Exist Value

I was working on a query that I found. It's a little bit more complex than I thought. This is part of each data document which is distinguished by an event name.
"eventTime" : "2021-07-11T08:29:00-0800",
"userId" : "P9QuPERPURPC3swJpyBb4",
"eventName" : "mko", // mko and mkp are two possible values
"eventData" : {}
The target is: userIds who have eventName('mko') AND does not have eventName('mkp')
I could not precisely understand what is the best way to handle 'not exist' in Elasticsearch queries. I'd appreciate any help.
I think the below queries might help you.
Get a user with the name mko:
{
"query": {
"bool": {
"must": [
{
"term": {
"eventName": "mko"
}
}
]
}
}
}
Get a user with a name other than mko:
{
"query": {
"bool": {
"must_not": [
{
"term": {
"eventName": "mko"
}
}
]
}
}
}
Get a user with the name mkp:
{
"query": {
"bool": {
"must": [
{
"term": {
"eventName": "mkp"
}
}
]
}
}
}
Get a user with a name other than mkp:
{
"query": {
"bool": {
"must_not": [
{
"term": {
"eventName": "mkp"
}
}
]
}
}
}
To get the selected fields only you can use the _source field in query: https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html.
And to check whether the field eventName is exists in a document. You can use the exists query within the must queries: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html

How to create a conditional node with JMESPath

With JMESPath based on the following:
If the input is
{ "app": { "usertype": "power" } }
I would like to create
{ "output": { "aslist": true } }
If the input is
{ "app": { "usertype": "simple" } }
I would like to create:
{ "output": { "aslist": false } }
I can create the output but not the conditional part. Seems like a simple if then else but I can't find any documentation on that.
Any suggestions?
You can simply use the evaluation of a condition in JMESPath as a value for your resulting JSON.
Given the query:
{output: {aslist: app.usertype == 'power'}}
On your example JSON:
{
"app": {
"usertype": "power"
}
}
This would give
{
"output": {
"aslist": true
}
}
On your example JSON:
{
"app": {
"usertype": "simple"
}
}
This would give
{
"output": {
"aslist": false
}
}
But, of course, since it is a simple evaluation of a condition based on your simplified example it would also give you a false for anything that is not of usertype being power.

SQL Server Replace in MongoDB

I want to do a replace in projection. Like a SQL Server REPLACE. I'm pretty sure we can handle that in code but looking for some shell commands.
Here is what I have
db.OrderHistoryHeader.aggregate([
{
$project:{
"_id":0,
"OrderNo":1 // I want to do Replace(OrderNo,'XYZ','ABC')
}
}
],
{
allowDiskUse:true
}).pretty();
There's no built-in operator for that currently but you can use $indexOfBytes combined with $substr and $concat.
db.OrderHistoryHeader.aggregate([
{
$addFields:
{
index: { $indexOfBytes: [ "$OrderNo", "XYZ" ] },
}
},
{
$project: {
OrderNo: {
$concat: [
{ $substr: [ "$OrderNo", 0, "$index" ] },
"ABC",
{ $substr: [ "$OrderNo", { $add: [3, "$index"] }, -1 ] }
]
}
}
},
{
$project: {
index: 0
}
}
])
Where 3 is the length of text being replaced.
You can use the replaceOne method
db.collection.replaceOne(filter, replacement, options)
From documentation:
Behavior
replaceOne() replaces the first matching document in the collection that matches the filter, using the replacement document.
upsert
If upsert: true and no documents match the filter, db.collection.replaceOne() creates a new document based on the replacement document.

How to retrieve null lookup entries on mongodb?

I have this query that provides me the join I want to:
db.summoners.aggregate([
{ "$match": { "nick":"Luispfj" } },
{ "$unwind": "$matches" },
{
"$lookup": {
"from":"matches",
"localField":"matches.gameId",
"foreignField":"gameId",
"as":"fullMatches"
}
},
{ "$unwind": "$fullMatches" },
{
"$group": {
"_id": null,
"matches": { "$push":"$fullMatches" }
}
}
])
But when I run the unwind function the null entries are gone. How do I retrieve them (with their respective "gameId"s, if possible?
Also, is there a way to retrieve only the matches array, instead of it being a subproperty of the "null-id-object" it creates?
$unwind takes an optional field preserveNullAndEmptyArrays which by default is false. If you set it to true, unwind will output the documents that are null. Read more about $unwind
{
"$unwind": {
path: "$fullMatches",
preserveNullAndEmptyArrays: true
}
},