How to check if a key element exists and if present update it? - mule

I am using mule community edition. So no Dataweave. I am consuming a rest service in my application. In the json response from this backend rest service. I need to check if a particular element exists inside muliple multiple elements of an array and wherever it exists I need to update its value.
E.g. (sample)
Input Request : [ { "id" : "1", "item" : "car", "make" : "Tonda" }, { "id" : "1", "item" : "car" } ]
using foreach to iterate array . Inside for each need to do something like below in expression component.
if( payload.make exists) { payload.make = "Tero"; }
But I do not know , how to check "if element exists"" condition. I tried below in expression component
if( payload.make != empty) { payload.make = "Tero"; }
But it did not work and gives error "Execution of the expression failed (org.mule.api.expression.ExpressionRuntimeException)"" for each array element wherever the particular key(make) is not present

inside foreach use the expression: #[payload.containsKey('make')] to check if the json key make exists or not. This will return true or false
Easy and simple!
Ref: https://forums.mulesoft.com/questions/71478/how-to-check-if-a-key-element-exists-and-if-presen.html?childToView=71502#answer-71502

Tested in a flow, if your payload is a single object and not a collection you can do MEL:
#[(payload.?make != empty) ? "EXISTS" : " OPS NO"]
Just change "EXISTS" with your true condition and "OPS NO" with the false one.
According to documentation: https://docs.mulesoft.com/mule-user-guide/v/3.7/mule-expression-language-reference
Null Safety
To access properties in a null safe manner, add the .? operator before one or more objects in a chain. In the following expression, if fieldA is null, the expression evaluates to null instead of a NullPointerException.

Related

Lua script access object path inside an array

I'm trying to access the object with property optionId = 'a386ead3-08ca-486e-aeb1-23add87292e7' to set its weight.
my object is like following:
weight": {
"options": [
{
"optionId": "a386ead3-08ca-486e-aeb1-23add87292e7",
"weight": 10
},
{
"optionId": "a386ead3-08ca-486e-aeb1-23add87292e7",
"weight": 20
}
],
"value": 100
}
and i'm using the following function to get its path but with no luck:
local GetFieldOptionWeightPath = function (optionId)
return "$.weight.options[\"optionId\"==\""..optionId.."\"]";
end
You need to compare each optionId like you would programmatically. To do that, you can use a filter script expression:
$.weight.options[?(#.optionId=="a386ead3-08ca-486e-aeb1-23add87292e7")]
Here, $() is the filter and # will point to each of the elements that's getting filtered.
Note that since it's a filter, it may potentially yield multiple results. In fact, in your example case it will yield both entries as they have the same optionId.
In the end your Lua function generating the path can look like:
local GetFieldOptionWeightPath = function (optionId)
return ("$.weight.options[?(#.optionId==%q)]"):format(optionId)
end
This answer assumes JSONPath support which was implemented in RedisJSON v2 (late 2021).

SailsJS, Waterline populate records with select

I have looked at a lot of old SO questions which have broken GitHub links and SailsJS Trello, however I am still unclear.
Is it possible, to populate a field (one-to-one relationship) in SailsJS and return only specific fields (either via select or omit).
await Document.find({id: id}).populate('createdBy', {select: ['name']})
I am getting
UsageError: Invalid populate(s).
Details:
Could not populate `createdBy` because of ambiguous usage. This is a singular ("model") association, which means it never refers to more than _one_ associated record. So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association
, since it generally wouldn't make any sense. But that's the trouble-- it looks like some sort of a subcriteria (or something) _was_ provided!
(Note that subcriterias consisting ONLY of `omit` or `select` are a special case that _does_ make sense. This usage will be supported in a future version of Waterline.)
Here's what was passed in:
{ select: [ 'name' ] }
In models,
createdBy: {
model: 'user',
description: 'Who is this document assigned to'
},
I am using sails 1.1.0, waterline 0.13.5-0
Am I doing this right? Is there a way to do this?
I solved the problem and made a pull request. Since the pull request has not yet been accepted, be careful and use it on your ask.
Go to
node_modules/waterline/lib/waterline/utils/query/forge-stage-two-query.js
Go to this section
// If this is a singular ("model") association, then it should always have
// an empty dictionary on the RHS. (For this type of association, there is
// always either exactly one associated record, or none of them.)
if (populateAttrDef.model) {....}
Change it to:
if (populateAttrDef.model) {
// Tolerate a subcriteria of `{}`, interpreting it to mean that there is
// really no criteria at all, and that we should just use `true` (the
// default "enabled" value for singular "model" associations.)
if (_.isEqual(query.populates[populateAttrName], {})) {
query.populates[populateAttrName] = true;
}
// Otherwise, this simply must be `true`. Otherwise it's invalid.
else {
if (query.populates[populateAttrName] !== true && (_.isUndefined(query.populates[populateAttrName].select) && _.isUndefined(query.populates[populateAttrName].omit))) {
throw buildUsageError(
'E_INVALID_POPULATES',
'Could not populate `'+populateAttrName+'` because of ambiguous usage. '+
'This is a singular ("model") association, which means it never refers to '+
'more than _one_ associated record. So passing in subcriteria (i.e. as '+
'the second argument to `.populate()`) is not supported for this association, '+
'since it generally wouldn\'t make any sense. But that\'s the trouble-- it '+
'looks like some sort of a subcriteria (or something) _was_ provided!\n'+
'(Note that subcriterias consisting ONLY of `omit` or `select` are a special '+
'case that _does_ make sense. This usage will be supported in a future version '+
'of Waterline.)\n'+
'\n'+
'Here\'s what was passed in:\n'+
util.inspect(query.populates[populateAttrName], {depth: 5}),
query.using
);
}//-•
else {
query.populates[populateAttrName] = {
select: query.populates[populateAttrName].select? query.populates[populateAttrName].select : undefined,
omit: query.populates[populateAttrName].omit? query.populates[populateAttrName].omit : undefined
};
}
}//>-•
}
This is the pull request to see exactly what you should change:
https://github.com/balderdashy/waterline/pull/1613
When u use One-to-one association u can't use subcriteria like error say.
So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association
U can use customToJSON function on model createdBy to omit data.
customToJSON: function() {
return _.omit(this, ['createdAt', 'updatedAt', 'id'])
}

query for Time Stamp in mongo [duplicate]

I have a problem when querying mongoDB with nested objects notation:
db.messages.find( { headers : { From: "reservations#marriott.com" } } ).count()
0
db.messages.find( { 'headers.From': "reservations#marriott.com" } ).count()
5
I can't see what I am doing wrong. I am expecting nested object notation to return the same result as the dot notation query. Where am I wrong?
db.messages.find( { headers : { From: "reservations#marriott.com" } } )
This queries for documents where headers equals { From: ... }, i.e. contains no other fields.
db.messages.find( { 'headers.From': "reservations#marriott.com" } )
This only looks at the headers.From field, not affected by other fields contained in, or missing from, headers.
Dot-notation docs
Since there is a lot of confusion about queries MongoDB collection with sub-documents, I thought its worth to explain the above answers with examples:
First I have inserted only two objects in the collection namely: message as:
> db.messages.find().pretty()
{
"_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
"headers" : {
"From" : "reservations#marriott.com"
}
}
{
"_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
"headers" : {
"From" : "reservations#marriott.com",
"To" : "kprasad.iitd#gmail.com"
}
}
>
So what is the result of query: db.messages.find({headers: {From: "reservations#marriott.com"} }).count()
It should be one because these queries for documents where headers equal to the object {From: "reservations#marriott.com"}, only i.e. contains no other fields or we should specify the entire sub-document as the value of a field.
So as per the answer from #Edmondo1984
Equality matches within sub-documents select documents if the subdocument matches exactly the specified sub-document, including the field order.
From the above statements, what is the below query result should be?
> db.messages.find({headers: {To: "kprasad.iitd#gmail.com", From: "reservations#marriott.com"} }).count()
0
And what if we will change the order of From and To i.e same as sub-documents of second documents?
> db.messages.find({headers: {From: "reservations#marriott.com", To: "kprasad.iitd#gmail.com"} }).count()
1
so, it matches exactly the specified sub-document, including the field order.
For using dot operator, I think it is very clear for every one. Let's see the result of below query:
> db.messages.find( { 'headers.From': "reservations#marriott.com" } ).count()
2
I hope these explanations with the above example will make someone more clarity on find query with sub-documents.
The two query mechanism work in different ways, as suggested in the docs at the section Subdocuments:
When the field holds an embedded document (i.e, subdocument), you can either specify the entire subdocument as the value of a field, or “reach into” the subdocument using dot notation, to specify values for individual fields in the subdocument:
Equality matches within subdocuments select documents if the subdocument matches exactly the specified subdocument, including the field order.
In the following example, the query matches all documents where the value of the field producer is a subdocument that contains only the field company with the value 'ABC123' and the field address with the value '123 Street', in the exact order:
db.inventory.find( {
producer: {
company: 'ABC123',
address: '123 Street'
}
});

Logstash condition to check if message contains any of from list of string

I have a javastack trace in message field and an array field having list of string like ["NullPointer", "TimeOutException"].
I want a conditional check on message field such that it checks if message contains any of from list of string.
Any idea how to get this?
It's a bit of a hack, but check out the translate{} filter. You could define your fields to translate to "1" (true, etc), with a default of "0". Then check that value to determine if it was in the set.
EDIT: for those who don't like to fish:
filter {
translate {
field => myInputField
dictionary => [
"NullPointer", 1,
"TimeOutException", 1
]
fallback => 0
destination => myOutputField
}
if [myOutputField] == "1" {
# it contained one of the items in the dictionary
...
}
else {
# it did not contain one of the items in the dictionary
...
}
}

In MongoDB, is there anyway to tell what index is on a collection besides using coll.find({...}).explain()?

I think explain() will tell any possible index it can use. How about just showing all the indexes defined on the collection? (or even for the whole db?)
>db.system.indexes.find();
>db.system.indexes.find( { ns: "tablename" } );
will give you something like
{
"ns" : "test.fs.chunks",
"key" : { "files_id" : 1, "n" : 1 },
"name" : "files_id_1_n_1"
}
for every index (ns is the collection name).
Or use the collection name. I.e., if you have a users collection do:
db.users.getIndexes()