Is there any way where we can generate output file based on the input data in benthos? - etl

For example:
Input Data:
{"date":"03-11-22", "message":"This is message"},
{"date":"03-30-22", "message":"This is message"},
{"date":"04-03-22", "message":"This is message"},
{"date":"04-15-22", "message":"This is message"},
{"date":"08-18-22", "message":"This is message"},
{"date":"08-28-22", "message":"This is message"}
The output should generate the file name according to the month and push the data in that month's file.
Output: Given input should create 3 files,
032022_data.log
042022_data.log
082022_data.log

The path field of the file output supports interpolation. Please try the following config:
input:
generate:
mapping: |
root = [
{"date":"03-11-22", "message":"This is message"},
{"date":"03-30-22", "message":"This is message"},
{"date":"04-03-22", "message":"This is message"},
{"date":"04-15-22", "message":"This is message"},
{"date":"08-18-22", "message":"This is message"},
{"date":"08-28-22", "message":"This is message"}
]
count: 1
interval: 0s
processors:
- unarchive:
format: json_array
output:
file:
path: ${! json("date").replace_all("-", "") }_data.log
It produces the following files:
031122_data.log
033022_data.log
040322_data.log
041522_data.log
081822_data.log
082822_data.log
Update: Based on the comments, I believe this pipeline should do what you need:
input:
generate:
mapping: |
root = [
{"date":"03-11-22", "message":"This is message"},
{"date":"03-30-22", "message":"This is message"},
{"date":"04-03-22", "message":"This is message"},
{"date":"04-15-22", "message":"This is message"},
{"date":"08-18-22", "message":"This is message"},
{"date":"08-28-22", "message":"This is message"}
]
count: 1
interval: 0s
processors:
- unarchive:
format: json_array
- mapping: |
meta month = this.date.re_replace_all("-.*-","")
- group_by_value:
value: ${! meta("month") }
- select_parts:
parts:
- 1
output:
file:
path: ${! meta("month") }_data.log
It creates these files:
0322_data.log
0422_data.log
0822_data.log
I'm not really sure where that 20 in between the month and the year is supposed to come from, so I left it out.

Related

Cannot return null for non-nullable type: 'null' within parent 'Model*Connection' (graphql, amplify)

I am working on an Amplify app that uses ReactJS, GraphQL, and DynamoDB. When a user creates an Event the response includes both the created Event as well as a non-nullable error. The event DOES successfully get created but the response includes an error. The error does not regard the Event table but the EventUsers connection (path: /createEvent/checked_in_users/items) of a many-to-many relationship with the User. I am unsure why this error occurs because the "checked_in_users" field is a nullable array. When I look at the schema.json file I see a NON_NULL in the ModelUserEventsConnection that looks like it could be the source of the error. But why would the UserEvents model fields default to non-nullable?
Call:
const createEventResponse = await API.graphql(graphqlOperation(createEvent, {input: data}));
Response:
{
data:
createEvent: {
id: '12345',
checked_in_users: null
description: "Lorem Ipsum",
start_date: '2023-01-23',
start_time: '2023-01-23T21:00:00.821Z',
end_time: '2023-01-23T22:00:00.247Z',
email: name#email.com
location_name: "Venue"
}
errors: Array(1)
0:
locations: null
message: "Cannot return null for non-nullable type: 'null' within parent 'ModelUserEventsConnection' (/createEvent/checked_in_users/items)"
path: Array(3)
0: "createEvent"
1: "checked_in_users"
2: "items"
}
Event Schema:
type Event #model #auth(
rules: [
{allow: public, operations: [read]},
{allow: private, operations: [read]},
{allow: groups, groups: ["Admin"]}
]) {
id: ID!
description: String
start_date: AWSDate
start_time: AWSDateTime
end_time: AWSDateTime
email: String
location_name: String
checked_in_users: [User] #manyToMany(relationName: "UserEvents") #auth(rules: [
{allow: groups, groups: ["Admin"], operations: [read]}
{allow: groups, groups: ["Users"], operations: [read, create, update]}
])
}
schema.json (possible source of the error):
{
"kind" : "OBJECT",
"name" : "ModelUserEventsConnection",
"description" : null,
"fields" : [ {
"name" : "items",
"description" : null,
"args" : [ ],
"type" : {
"kind" : "NON_NULL",
"name" : null,
"ofType" : {
"kind" : "LIST",
"name" : null,
"ofType" : {
"kind" : "OBJECT",
"name" : "UserEvents",
"ofType" : null
}
}
},
"isDeprecated" : false,
"deprecationReason" : null
...
}
I used the AWS AppSync query tool to test the createEvent mutation and getEvent query and they both work without any issues. I tested the onEventCreate subscription as well and saw that it returns an event with null for all fields and throws an error for the null value AWSDateTime createdAt and updatedAt fields if I include them. Considering the Event does successfully get created on the app, could the issue have something to do with the subscription? Why would it return all null values? Then again, the error points specifically to the connection.

How to groupBy and count the pivot table in laravel?

I have three tables,
User cities user_cities
id name title id name user_id city_id
1 aaa designer 1 cityA 2 1
2 bbb developer 2 cityB 2 2
3 ccc designer 3 cityC 1 2
1 1
2 3
3 2
After joining and querying the database my result is,
data: {
0: {
id: 1
name: aaa,
title: designer,
cities :[
0: {
id: 1,
name: cityA
}
1: {
id: 2,
name: cityB
}
2: {
id: 3,
name: cityC
}
]
},
1: {
id: 2
name: bbb,
title: developer,
cities :[
0: {
id: 1,
name: cityA
}
1: {
id: 2,
name: cityB
}
]
}
1: {
id: 3
name: ccc,
title: designer,
cities :[
0: {
id: 2,
name: cityB
}
]
}
}
Everything is fine until here. But i want to groupBy by cities and take count.
If i filter by title=designer the filtered data will display and i want to make group by cities and take count of it.
So my final result will be,
cityA = 1 counts
cityC = 2 counts
Help me to solve the problem.
You might use the withCount to eager load the relationship counts.
I assume you already have the cities relationship defined in the User.php model:
class User
{
public function cities()
{
return $this->belongsToMany(City::class);
}
}
Then:
$users = User::withCount('cities')->get();
I think the results are gonna be:
data: {
0: {
id: 1
name: aaa,
title: designer,
cities_count: 3
},
1: {
id: 2
name: bbb,
title: developer,
cities_count: 2
}
1: {
id: 3
name: ccc,
title: designer,
cities_count: 1
}
}
An alternative could be using lazy eager loading:
$users = User::all()->loadCount('cities');

Spring Data MongoDB Aggregation with "ReplaceRoot"

Please assist in transforming below MongoDB query in a Spring Data Application.
db.test_contents.aggregate([
{$match: { $and: [
{"domain": "google.com"},
{"locale": {$in: ["en-in", "en-us"]}},
{"contents.contentName": "Template1"}
]
}
},
{$unwind: "$contents"},
{$unwind: "$contents.fields"},
{$match: { "contents.fields.title": {$in: ["Company Name"]}}},
{$group: { "_id": "$_id",
"contents": { "$push": "$contents" },
"root": {$first:"$$ROOT"} }},
{$replaceRoot:{newRoot:{$mergeObjects:["$root",{contents:'$contents'}]}}}
]);
Does anyone know how to add the replaceRoot to my Aggregation?
What we tried,but didnt work
MatchOperation matchOperation = match(where("domain").is("google.com").andOperator(
where("contents.contentName").is("Template1"),
where("locale").in(requestBody.getLocales())));
UnwindOperation unwindOperation = unwind("contents");
UnwindOperation unwindOperation1 = unwind("contents.fields");
MatchOperation matchOperation1 = match(where("contents.fields.title").in("First Name"));
GroupOperation groupOperation = group("id").push("$contents").as("contents").first(Aggregation.ROOT).as("root");
Error came as (changed some values or field names intentionally)
{
"timestamp": "2019-02-06T07:43:04.843+0000",
"message": "Command failed with error 40400 (Location40400): '$mergeObjects requires object inputs, but input [{contentName: \"Template_1\", fields: {alternateText: \"First Name alternate text.\", description: \"First Name description.\", fieldId: \"firstname\", fieldType: \"Plain Text\", placeholder: \"Enter your first name.\", title: \"First Name\", value: \"Joginder\"}}] is of type array' on server 127.0.0.1:27017. The full response is { \"ok\" : 0.0, \"errmsg\" : \"$mergeObjects requires object inputs, but input [{contentName: \\\"Template_1\\\", fields: {alternateText: \\\"First Name alternate text.\\\", description: \\\"First Name description.\\\", fieldId: \\\"firstname\\\", fieldType: \\\"Plain Text\\\", placeholder: \\\"Enter your first name.\\\", title: \\\"First Name\\\", value: \\\"Joginder\\\"}}] is of type array\", \"code\" : 40400, \"codeName\" : \"Location40400\" }; nested exception is com.mongodb.MongoCommandException: Command failed with error 40400 (Location40400): '$mergeObjects requires object inputs, but input [{contentName: \"Template_1\", fields: {alternateText: \"First Name alternate text.\", description: \"First Name description.\", fieldId: \"firstname\", fieldType: \"Plain Text\", placeholder: \"Enter your first name.\", title: \"First Name\", value: \"test\"}}] is of type array' on server 127.0.0.1:27017. The full response is { \"ok\" : 0.0, \"errmsg\" : \"$mergeObjects requires object inputs, but input [{contentName: \\\"Template_1\\\", fields: {alternateText: \\\"First Name alternate text.\\\", description: \\\"First Name description.\\\", fieldId: \\\"firstname\\\", fieldType: \\\"Plain Text\\\", placeholder: \\\"Enter your first name.\\\", title: \\\"First Name\\\", value: \\\"test\\\"}}] is of type array\", \"code\" : 40400, \"codeName\" : \"Location40400\" }",
"details": "uri=/test/test/template/Template_1/domain/test.com

How can I compare two rethinkdb objects to create a new object that only contains their differences?

Say I have two objects stored in rethinkdb I wish to compare, let's call them old_val and new_val. As an example, let's say these values represent a TODO task that has changed owner and status:
{
old_val: {
status: 'active',
content: 'buy apples',
owner: 'jordan'
},
new_val: {
status: 'done',
content: 'buy apples',
owner: 'matt'
}
}
When I compare old_val and new_val, I'd like to yield a new object where new_val only contains the fields that differ from old_val. I want to do this in order to save bytes on the wire; and make rendering changes on my client easier. The result of the query should look something like this:
{
old_val: {
content: 'buy apples',
owner: 'jordan',
status: 'active'
},
new_val: {
owner: 'matt',
status: 'done'
}
}
How would I do this?
There are three separate parts to solving this problem:
Generate a list of fields to compare
Compare between common fields, include only fields which differ
Create a new object
(1) A list of fields can be generated by using the keys() method. We can filter these fields to (2) only include those which exist in both old_val and new_val and whose values differ. We can then pass this sequence to concatMap() to build an array of key/value pairs like [key0, value0, key1, value1]. Finally, a new object can be constructed (3) from this sequence by applying it as arguments (using r.args()) to the r.object() function.
It comes together like this:
r.expr({
old_val: {
status: 'active',
content: 'buy apples',
owner: 'jordan'
},
new_val: {
status: 'done',
content: 'buy apples',
owner: 'matt'
}
}).do((diff_raw) =>
r.expr({
old_val: diff_raw('old_val'),
// build an object only containing changes between old_val and new_val:
new_val: r.object(r.args(
diff_raw('new_val')
.keys()
// only include keys existing in old and new that have changed:
.filter((k) =>
r.and(
diff_raw('old_val').hasFields(k),
diff_raw('new_val')(k).ne(diff_raw('old_val')(k))
)
)
// build a sequence of [ k0, v0, k1, v1, ... ]:
.concatMap((k) => [k, diff_raw('new_val')(k)])
))
})
)
This will return:
{
"new_val": {
"owner": "matt" ,
"status": "done"
} ,
"old_val": {
"content": "buy apples" ,
"owner": "jordan" ,
"status": "active"
}
}

kendoui kendoGrid datasource aggregate to existing data

I hope this question hasn't been asked elsewhere but I'm running into an issue with a kendoGrid and adding aggregates. This is an existing grid bound to a data Source that is an array.
What is the best way to add an aggregate to an existing data Source?
Here is what I'm doing to bind to the existing data Source:
var grid = $("#myGrid").data("kendoGrid");
grid.dataSource.data(myArray);
Once you set the data you can add new aggregate like shown in the documentation.
var dataSource= new kendo.data.DataSource({
data: [
{ name: "Jane Doe", age: 30 },
{ name: "John Doe", age: 33 }
]
});
// calculate the minimum and maximum age
dataSource.aggregate([
{ field: "age", aggregate: "min" },
{ field: "age", aggregate: "max" }
]);
var ageAggregates = dataSource.aggregates().age;
console.log(ageAggregates.min); // displays "30"
console.log(ageAggregates.max); // displays "33"

Resources