Get sum of the values of objects in an array - mule

I have a dataweave input as given below.
%dw 2.0
output application/json
var demo = [
{
"mat" : 1000,
"seg" : "z"
},
{
"mat" : 2000,
"seg" : "b"
},
{
"mat" : 3000,
"seg" : "x"
}
]
var count = 0
---
count
I need the sum of the "mat" field, the count should 6000. How do I achieve this ?

I did it like this
%dw 2.0
output application/json
var demo = [
{
"mat" : 1000,
"seg" : "z"
},
{
"mat" : 2000,
"seg" : "b"
},
{
"mat" : 3000,
"seg" : "x"
}
]
var count = sum(demo.mat)
---
count

Related

How to get last second of every minute from mongoDB using SQL query

I have a table with records for every millisecond. I need to get only the last second of every minute using Mongodb sql query.
Id Balance DataTime
1 "2462188.61" 2019-09-27T05:49:33.575+00:00
1 "2449426.30" 2019-10-30T19:30:52.513+00:00
1 "2456459.67" 2019-10-15T18:20:09.490+00:00
5 "1006266.91" 2019-10-31T13:48:18.290+00:00
I tried the LIKE condition but that didn't work.
Select Id, DateTime,Balance from AccountBalance where DateTime like '%59.000%'
Here is the link for the mongoldb SQL reference :
https://docs.mongodb.com/bi-connector/current/supported-operations/
I am using the BI connector to connect to Tableau(hence need the sql version of the query)
Thanks in advance!
You could try...
db.z.aggregate([
{ $addFields: {
year: { $dateToString: { format: "%Y", date: "$DataTime" } },
month: { $dateToString: { format: "%m", date: "$DataTime" } },
day: { $dateToString: { format: "%d", date: "$DataTime" } },
hour: { $dateToString: { format: "%H", date: "$DataTime" } },
minute: { $dateToString: { format: "%M", date: "$DataTime" } },
second: { $dateToString: { format: "%S", date: "$DataTime" } }
}
}
]).pretty()
This assumes your field DataTime is of type ISODate()...
Example Documents:
{ "_id" : ObjectId("5dea94c3b4ae6bbc17cd023b"), "Balance" : "2462188.61", "DataTime" : ISODate("2019-09-27T05:49:33.575Z") }
{ "_id" : ObjectId("5dea94c3b4ae6bbc17cd023c"), "Balance" : "2449426.30", "DataTime" : ISODate("2019-10-30T19:30:52.513Z") }
{ "_id" : ObjectId("5dea94c3b4ae6bbc17cd023d"), "Balance" : "2456459.67", "DataTime" : ISODate("2019-10-15T18:20:09.490Z") }
{ "_id" : ObjectId("5dea94c3b4ae6bbc17cd023e"), "Balance" : "1006266.91", "DataTime" : ISODate("2019-10-31T13:48:18.290Z") }
Example Query Output:
{
"_id" : ObjectId("5dea94c3b4ae6bbc17cd023b"),
"Balance" : "2462188.61",
"DataTime" : ISODate("2019-09-27T05:49:33.575Z"),
"year" : "2019",
"month" : "09",
"day" : "27",
"hour" : "05",
"minute" : "49",
"second" : "33"
}
{
"_id" : ObjectId("5dea94c3b4ae6bbc17cd023c"),
"Balance" : "2449426.30",
"DataTime" : ISODate("2019-10-30T19:30:52.513Z"),
"year" : "2019",
"month" : "10",
"day" : "30",
"hour" : "19",
"minute" : "30",
"second" : "52"
}
{
"_id" : ObjectId("5dea94c3b4ae6bbc17cd023d"),
"Balance" : "2456459.67",
"DataTime" : ISODate("2019-10-15T18:20:09.490Z"),
"year" : "2019",
"month" : "10",
"day" : "15",
"hour" : "18",
"minute" : "20",
"second" : "09"
}
{
"_id" : ObjectId("5dea94c3b4ae6bbc17cd023e"),
"Balance" : "1006266.91",
"DataTime" : ISODate("2019-10-31T13:48:18.290Z"),
"year" : "2019",
"month" : "10",
"day" : "31",
"hour" : "13",
"minute" : "48",
"second" : "18"
}
use sort function with date
eg:
db.collection.find().sort("Date_Field")

How do I sum up two fields in the Mongoshell?

I have a find statement in a store database that looks like this:
db.Purchases.find( {}, { store: 1, total: 1, _id: 0 } ).sort( { "store" : 1} ) =
{ "store" : DBRef("Location", ObjectId("5dae22702486f7d89ba7633c")), "total" : "$1500" }
{ "store" : DBRef("Location", ObjectId("5dae227f2486f7d89ba7633d")), "total" : "$156.88" }
{ "store" : DBRef("Location", ObjectId("5dae22992486f7d89ba7633e")), "total" : "$1510" }
{ "store" : DBRef("Location", ObjectId("5dae22992486f7d89ba7633e")), "total" : "$3000" }
{ "store" : DBRef("Location", ObjectId("5dae22cd2486f7d89ba76340")), "total" : "$156.88" }
I need to sum the totals from output 3 and 4 (i.e $1510 and $3000) and display the result as one line in the output along all the other outputs. How do I do this?
Try this:
db.Purchases.aggregate(
[
{
$group:
{
_id: "$store",
totalAmount: { $sum: "$total"}
}
}
]
)
Observation: total must be a numeric type in MongoDB.

mongodb query multiple pairs using $in

I have a collection names with data (_id is omitted):
{first:"John", last:"Smith"},
{first:"Alice", last:"Johnson"},
{first:"Bob", last:"Williams"},
...
and {first, last} is a unique index.
I want to find a lot of names in names like:
db.names.find({$or: [{first:"Alice", last:"Brown"}, {first:"Bob", last:"White"}, ...]}
Can I use $in instead of $or to simplify this query?
===
I know in MySQL this following query:
SELECT * FROM names WHERE (first = 'Alice' AND last = 'Brown') OR (first = 'Bob' AND last = 'White') OR ...
can be simplified as:
SELECT * FROM names WHERE (first, last) IN (('Alice', 'Brown'), ('Bob','White') OR ...)
But I am unable to find the equivalent query syntax in MongoDB.
The following query can get us the expected output:
db.names.find({
$expr:{
$in:[
{
"first":"$first",
"last":"$last"
},
[
{
"first" : "Alice",
"last" : "Johnson"
},
{
"first" : "Bob",
"last" : "Williams"
}
]
]
}
}).pretty()
Data set:
{
"_id" : ObjectId("5d81c3b7a832f81a9e02337b"),
"first" : "John",
"last" : "Smith"
}
{
"_id" : ObjectId("5d81c3b7a832f81a9e02337c"),
"first" : "Alice",
"last" : "Johnson"
}
{
"_id" : ObjectId("5d81c3b7a832f81a9e02337d"),
"first" : "Bob",
"last" : "Williams"
}
Output:
{
"_id" : ObjectId("5d81c3b7a832f81a9e02337c"),
"first" : "Alice",
"last" : "Johnson"
}
{
"_id" : ObjectId("5d81c3b7a832f81a9e02337d"),
"first" : "Bob",
"last" : "Williams"
}
Query Analysis: This query won't use the unique index you have created and I would recommend to go with the $or query.
Following are the winning plans:
$or query:
{
"stage" : "COLLSCAN",
"filter" : {
"$expr" : {
"$in" : [
{
"first" : "$first",
"last" : "$last"
},
{
"$const" : [
{
"first" : "Alice",
"last" : "Johnson"
},
{
"first" : "Bob",
"last" : "Williams"
}
]
}
]
}
},
"direction" : "forward"
}
$in query:
{
"stage" : "SUBPLAN",
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "OR",
"inputStages" : [
{
"stage" : "IXSCAN",
"keyPattern" : {
"first" : 1,
"last" : 1
},
"indexName" : "first_1_last_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"first" : [ ],
"last" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"first" : [
"[\"Alice\", \"Alice\"]"
],
"last" : [
"[\"Brown\", \"Brown\"]"
]
}
},
{
"stage" : "IXSCAN",
"keyPattern" : {
"first" : 1,
"last" : 1
},
"indexName" : "first_1_last_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"first" : [ ],
"last" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"first" : [
"[\"Bob\", \"Bob\"]"
],
"last" : [
"[\"White\", \"White\"]"
]
}
}
]
}
}
}
You can see that the index is properly utilized in $or query and not used in the $in query.
For this mysql query
SELECT * FROM names
WHERE (first = 'Alice' AND last = 'Brown')
OR (first = 'Bob' AND last = 'White')
OR ...
can be use in mongodb as
db.names.find({
$or: [
{ first: "Alice", last: "Brown" },
{ first: "Bob", last: "White" },
...
]})
For below mysql query
SELECT * FROM names
WHERE (first, last) IN (('Alice', 'Brown'), ('Bob','White') OR ...)
You can not create mongodb $in query
db.names.find({
$or: [
{ first: { $in: ["John", "Alice", "Bob"] } },
{ last: { $in: ["Smith", "Johnson", "Williams" ] } },
]})
Because it pass this result too
("John", "Johnson"),("John", "Williams"),("John", "Smith"),("John", "Williams")..
the best way is $or as ask in question
db.names.find({
$or: [
{ first: "Alice", last: "Brown" },
{ first: "Bob", last: "White" },
...
]})
May be better solution present out there. I will update my answer if find any. Thanks
Yes, it's possible to use $in to query MongoDb collections based on multiple values.
Try using the below syntax:
db.names.find.({ field: { $in: [<value1>, <value2>, ... <valueN> ] } })
for example in your case it looks like:
db.names.find({first: {$in: ["Alice","Brown","Bob", "White"]}})

Replacing Null with Blank blank in Dataweave 2.0

I have to replace null with blanks in dataweave 2.0 , I tried many combinations but getting error in it .
The screenshot is attached for your reference .
Please provide any pointers for the same .
Thanks.
Its because you are assigning the blank string to dValue.doctorId and not (doctorId). Also using default is easier here for setting default values. Here is an example:
%dw 2.0
output application/xml
var doctorInformationList=[{doctorId: '1'},{doctorId: '2'}, {}]
---
root: {
DoctorInformationList: doctorInformationList map ((dValue, dIndex) ->
doctorId : dValue.doctorId default ""
)
}
It's better to use when - otherwise.
Below is dataweave transform for your problem
%dw 2.0
%output application/json
%var doctorInfoList=[{doctorId: '1', doctorName : 'A'},{doctorId: '2', doctorName : 'B'},
{doctorId: null, doctorName : 'C'},{doctorId: '', doctorName : 'D'},{}]
---
{
DoctorInfoList: doctorInfoList map ((doctorValue, doctorIndex) -> {
"docorId" : '' when doctorValue.doctorId is :null otherwise doctorValue.doctorId,
"docorName" : doctorValue.doctorName
}
)
}
Output would be like :
{
"DoctorInfoList": [
{
"docorId": "1",
"docorName": "A"
},
{
"docorId": "2",
"docorName": "B"
},
{
"docorId": "",
"docorName": "C"
},
{
"docorId": "",
"docorName": "D"
},
{
"docorId": "",
"docorName": null
}
]
}
Replace doctorInfoList with your payload

Lookup list of Maps variable in data weave script

I have a list of maps (listOfMapsObject) like below
[
{
"Id" : "1234",
"Value" : "Text1"
},
{
"Id" : "1235",
"Value" : "Text2"
}
]
I would like access "Value" field for a given Id in dataweave script.
For example: For Id = 1234, Text1 should be returned.
%dw 1.0
%output application/json
%var listOfMapsObject = flowVars.listOfMaps
---
payload map {
"key" : $.key,
"data" : lookup Value field in listOfMapsObject by given key
}
Approch suggested by #'sulthony h' is fine but it will end up in performance issue if you large number of data in pyload and listOfMapsObject. As filter is used , for each record of payload script will loop for all the entries in flowVars.listOfMaps.
Following will work fine and map key value only once.
%dw 1.0
%output application/json
%var dataLookup = {(flowVars.listOfMaps map {
($.Id): $.Value
})}
---
payload map {
key : $.key,
data : dataLookup[$.key]
}
Output-
[
{
"key": "1234",
"data": "Text1"
},
{
"key": "1235",
"data": "Text2"
}
]
Where Payload -
[
{
"key" : "1234"
},
{
"key" : "1235"
}
]
And -
[
{
"Id" : "1234",
"Value" : "Text1"
},
{
"Id" : "1235",
"Value" : "Text2"
}
]
Hope this helps.
I create my own object with the slightly similar object and successfully access "value" field with the following DataWeave expression:
%dw 1.0
%output application/json
%var listOfMapsObject = flowVars.listOfMaps
---
payload map using(data = $) {
"key" : data.key,
"data" : (listOfMapsObject filter $.id == data.key).value reduce ($$ ++ $)
}
You can modify it with your own object, e.g.: replace the "id" with "Id". Test and evaluate the result by using filter, flatten, reduce, etc.