Filer json by selecting a particular node - powershell-4.0

I am having my JSON as follows
{
"Root": [{
"Child": [{
"Id": "1"
}],
"Child1": [{
"Id": "2"
}]
}]
}
I am getting the content as follows
$content = (Get-Content -filepath) -join "`n" | ConvertFrom-Json
What I need is If I pass from the script as Child1 I need to extract the following node and show
"Child1": [{
"Id": "2"
}]

Since you're using PS3+, instead of joining the lines (it's slow), read the file as one string via -Raw:
$content = Get-Content $filepath -Raw | ConvertFrom-Json
Filtering by name, showing contents without name:
$name = 'Child1'
$content.Root.$name | ConvertTo-Json
In PS2.0:
$content.Root | Select -expand $name | ConvertTo-Json
Filtering by name, showing name and contents:
$name = 'Child1'
($content.Root | select $name | ConvertTo-Json) -replace '^.|.$',''
Filtering by Id, showing contents:
$content.Root | ForEach { $_.PSObject.Properties.Value | Where Id -eq 2 } |
ConvertTo-Json
Filtering by Id, showing name and contents of the node:
($content.Root |
ForEach {
$_.PSObject.Properties |
Where { $_.Value.Id -eq 2 } |
ForEach { #{$_.Name = $_.Value} }
} | ConvertTo-Json
) -replace '^.|.$',''

Related

with Powershell how browse a csv file and link the elements according to their types?

I need to link the job to the each subjob with the "RealizationRelationship" and the relation between previous and next subjob there are a "TriggeringRelationship" : the job is of this format for example ACGN100Q while the subjobs that are attached are sequential and of this format: ACGN-100Q-000T;ACGN-100Q-010T;ACGN-100Q-020T;ACGN-100Q-030T
In my csv file the type of this job ACGN100Q is "TechnologyInteraction" while the subjobs are of type "TechnologyService". I am developing a script that allows me to say for example that the link between ACGN-100Q-000T and ACGN-100Q-010T is of type "TrigerringRelation" and the link between ACGN100Q and ACGN-100Q-000T is of type "RealizationRelation". I need help because I can't make the link.
And finally the relationship between job of type "TechnologyInteraction" and job of type "TechnologyEvent" is of type "TriggeringRelationship
I have a beginning of answer in a previous post, but it turns out that had not understood the subject well, now what I am looking for is clear.
ID,"Type","Name","Documentation", "planification"
eb214110-2b6a-48b2-ba5a-7c13dc3bba39,"TechnologyInteraction","ACGN100Q","Begin Of JobStream"
a46681e7-19a8-4fc5-b747-09679c15ff26,"TechnologyService","ACGN-100Q-000T","Transfert UDM (xACGN000)"
85761a09-1145-4037-a527-66a743def45f,"TechnologyService","ACGN-100Q-010T","move fichier REF to work"
27b126fb-c708-427d-b0a6-ce4747114ac4,"TechnologyService","ACGN-100Q-020T","w_read_account"
bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82,"TechnologyService","ACGN-100Q-030T","w_read_referential"
0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97,"TechnologyService","ACGN-100Q-040T","w_load_CompanyGroup"
1f487986-3cac-4af8-bda2-6400a1c71f48,"TechnologyService","ACGN-100Q-050T","w_load_Company"
40bec2d6-4545-48c2-acd5-089a05d4a723,"TechnologyInteraction","ADMR061Q","Begin Of JobStream", "23h30"
14b2e8ce-cceb-4a72-a22b-1518ca582dfe,"TechnologyEvent","Create list files 23h30","ADMR-061Q-090T", "23h30"
fe7d7052-a3e5-4cea-a987-567e29fdf685,"TechnologyEvent","w_F_REF08_BROKER 23h30","ADMR-061Q-100T", "23h30"
ddc3713b-57ec-4152-8dc7-01b8166c969a,"TechnologyEvent","w_F_REF08_CEDENT 23h30","ADMR-061Q-100T", "23h30"
And I want to get a file that looks like this:
relation.csv
"ID","Type","Name","Documentation","Source","Target"
"New ID","RealizationRelationship","","","eb214110-2b6a-48b2-ba5a-7c13dc3bba39","a46681e7-19a8-4fc5-b747-09679c15ff26"
"New ID","RealizationRelationship","","","eb214110-2b6a-48b2-ba5a-7c13dc3bba39","85761a09-1145-4037-a527-66a743def45f"
"New ID","RealizationRelationship","","","eb214110-2b6a-48b2-ba5a-7c13dc3bba39","27b126fb-c708-427d-b0a6-ce4747114ac4"
"New ID","RealizationRelationship","","","eb214110-2b6a-48b2-ba5a-7c13dc3bba39","bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82"
"New ID","RealizationRelationship","","","eb214110-2b6a-48b2-ba5a-7c13dc3bba39","0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97"
"New ID","RealizationRelationship","","","eb214110-2b6a-48b2-ba5a-7c13dc3bba39","1f487986-3cac-4af8-bda2-6400a1c71f48"
"New ID","TriggeringRelationship","","","a46681e7-19a8-4fc5-b747-09679c15ff26","85761a09-1145-4037-a527-66a743def45f"
"New ID","TriggeringRelationship","","","85761a09-1145-4037-a527-66a743def45f","27b126fb-c708-427d-b0a6-ce4747114ac4"
"New ID","TriggeringRelationship","","","27b126fb-c708-427d-b0a6-ce4747114ac4","bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82"
"New ID","TriggeringRelationship","","","bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82","0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97"
"New ID","TriggeringRelationship","","","0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97","1f487986-3cac-4af8-bda2-6400a1c71f48"
"New ID","TriggeringRelationship","","","40bec2d6-4545-48c2-acd5-089a05d4a723","14b2e8ce-cceb-4a72-a22b-1518ca582dfe"
"New ID","TriggeringRelationship","","","40bec2d6-4545-48c2-acd5-089a05d4a723","fe7d7052-a3e5-4cea-a987-567e29fdf685"
"New ID","TriggeringRelationship","","","40bec2d6-4545-48c2-acd5-089a05d4a723","ddc3713b-57ec-4152-8dc7-01b8166c969a"
$result= #()
function linkedRelationCsvToElementsCsv{
Write-Host "beginning linkedRelationCsvToElementsCsv"
$elements2Csv=Import-Csv $path\elements.csv
$jobTypes = #( "TechnologyInteraction");
$jobTypes2= #("TechnologyEvent");
$subTypes = #( "TechnologyService");
$previousItem = $null;
foreach( $item in $elements2Csv )
{
if( $item.Type -in $jobTypes )
{
# start of a new job, but output the link between TWS and Job name
$result0= new-object PSCustomObject -Property ([ordered] #{
"ID" = [guid]::NewGuid().ToString()
"Type" = "RealizationRelationship"
"Name" = "";
"Documentation" = ""
"Source" ="ef2f510b-924b-439d-8720-0183c7294eb3"
"Target" = $item.ID
});
$result= $result + $result0
}
elseif( $item.Type -in $jobTypes2 )
{
# start of a new job, but output the link between TWS and Job name
$result3= new-object PSCustomObject -Property ([ordered] #{
"ID" = [guid]::NewGuid().ToString()
"Type" = "RealizationRelationship"
"Name" = "";
"Documentation" = ""
"Source" =$previousItem.ID
"Target" = $item.ID
});
$result= $result + $result3
}
elseif( $item.Type -in $subJobTypes)
{
# not a subjob type that we recognise
throw "unrecognised subjob type '$($item.Type)' for subjob '$($item.ID)'";
}
elseif( $null -eq $previousItem )
{
# we've got a subjob, but there was no previous job or subjob
throw "no preceding item for subjob '$($item.ID)' with name: '$($item.Name)'";
}
elseif( $previousItem.Type -in $jobTypes )
{
# this is the first subjob after the parent job
$result1= new-object PSCustomObject -Property ([ordered] #{
"ID" = [guid]::NewGuid().ToString()
"Type" = "TriggeringRelationship"
"Name" = ""
"Documentation" = ""
"Source" = $previousItem.ID
"Target" = $item.ID
});
$result= $result + $result1
}
else
{
# the preceding item was a subjob as well
$result2= new-object PSCustomObject -Property ([ordered] #{
"ID" = [guid]::NewGuid().ToString()
"Type" = "TriggeringRelationship"
"Name" = ""
"Documentation" = ""
"Source" = $previousItem.ID
"Target" = $item.ID
});
$result =$result + $result2
}
$previousItem = $item;
#$elements2Csv
Write-Host "previousItem value is '$($previousItem)' and Item value is '$($item)'"
}
$result |Select-Object -Property ID,"Type","Name","Documentation","Source","Target"| Export-Csv $path\relations.csv -NoTypeInformation -Encoding UTF8
notepad $path\relations.csv
Write-Host "Ending linkedRelationCsvToElementsCsv"
}linkedRelationCsvToElementsCsv # Call the function
You could do regex matches on the Name and Documentation based on an extrapolation of the master record's Name field (split it in half, drop a hyphen in the middle, and stick it back together). That'll match master to child easily enough. Then you just want to group them by parent and link one to the next? That should be simple enough.
$Records=#'
ID,"Type","Name","Documentation", "planification"
eb214110-2b6a-48b2-ba5a-7c13dc3bba39,"TechnologyInteraction","ACGN100Q","Begin Of JobStream"
a46681e7-19a8-4fc5-b747-09679c15ff26,"TechnologyService","ACGN-100Q-000T","Transfert UDM (xACGN000)"
85761a09-1145-4037-a527-66a743def45f,"TechnologyService","ACGN-100Q-010T","move fichier REF to work"
27b126fb-c708-427d-b0a6-ce4747114ac4,"TechnologyService","ACGN-100Q-020T","w_read_account"
bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82,"TechnologyService","ACGN-100Q-030T","w_read_referential"
0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97,"TechnologyService","ACGN-100Q-040T","w_load_CompanyGroup"
1f487986-3cac-4af8-bda2-6400a1c71f48,"TechnologyService","ACGN-100Q-050T","w_load_Company"
40bec2d6-4545-48c2-acd5-089a05d4a723,"TechnologyInteraction","ADMR061Q","Begin Of JobStream", "23h30"
14b2e8ce-cceb-4a72-a22b-1518ca582dfe,"TechnologyEvent","Create list files 23h30","ADMR-061Q-090T", "23h30"
fe7d7052-a3e5-4cea-a987-567e29fdf685,"TechnologyEvent","w_F_REF08_BROKER 23h30","ADMR-061Q-100T", "23h30"
ddc3713b-57ec-4152-8dc7-01b8166c969a,"TechnologyEvent","w_F_REF08_CEDENT 23h30","ADMR-061Q-100T", "23h30"
'# -split '[\r\n]+'|ConvertFrom-Csv
$HT = [Ordered]#{}
$Records|%{$HT.Add($_.ID,$_)}
$Relations = ForEach($Master in $Records|?{$_.Name -notmatch '-' -and $_.Documentation -notmatch '-'}){
$Child = $Master.Name -split '(?<=^.{4})' -join '-'
$Children = $Records|?{$_.Name -match "(.*$child.*)" -or $_.Documentation -match "(.*$child.*)"}|%{
[pscustomobject]#{
"ID" = [guid]::NewGuid().ToString()
"Type" = "RealizationRelationship"
"Name" = "";
"Documentation" = ""
"Source" =$Master.ID
"Target" = $_.ID
}
}
$Children
$Children|Group Source|%{
For($i=1;$i -lt $_.Group.Count;$i++){
[PSCustomObject]#{
"ID" = [guid]::NewGuid().ToString()
"Type" = "TriggeringRelationship"
"Name" = ""
"Documentation" = ""
"Source" = $_.Group[$i-1].Target
"Target" = $_.Group[$i].Target
}
}
}
}
$Relations|ft
That outputs:
ID Type Name Documentation Source Target
-- ---- ---- ------------- ------ ------
9113f645-831a-4c86-9518-d8b0c95eae7a RealizationRelationship eb214110-2b6a-48b2-ba5a-7c13dc3bba39 a46681e7-19a8-4fc5-b747-09679c15ff26
db4436be-7dd7-4bba-8387-32ed97ed9885 RealizationRelationship eb214110-2b6a-48b2-ba5a-7c13dc3bba39 85761a09-1145-4037-a527-66a743def45f
94cc2eb4-63cf-4cae-a139-1628307e938b RealizationRelationship eb214110-2b6a-48b2-ba5a-7c13dc3bba39 27b126fb-c708-427d-b0a6-ce4747114ac4
c738adf7-dddb-45d3-aa99-ceb2113b969b RealizationRelationship eb214110-2b6a-48b2-ba5a-7c13dc3bba39 bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82
11d94a45-2313-45b8-94d5-e5422bfc15c2 RealizationRelationship eb214110-2b6a-48b2-ba5a-7c13dc3bba39 0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97
b1ff9e89-301d-4681-b6b5-d8418c41299d RealizationRelationship eb214110-2b6a-48b2-ba5a-7c13dc3bba39 1f487986-3cac-4af8-bda2-6400a1c71f48
25d4eb64-d580-40cd-9f7a-ff1c41217875 TriggeringRelationship a46681e7-19a8-4fc5-b747-09679c15ff26 85761a09-1145-4037-a527-66a743def45f
5a9f160e-5956-4a70-b8cb-ccfca764f772 TriggeringRelationship 85761a09-1145-4037-a527-66a743def45f 27b126fb-c708-427d-b0a6-ce4747114ac4
c04434d3-1a22-47ba-a057-df430be0d5a9 TriggeringRelationship 27b126fb-c708-427d-b0a6-ce4747114ac4 bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82
b50754f9-145e-44a9-92ee-c1bceb8dea71 TriggeringRelationship bb0c5e42-5fad-4bd9-8ee9-f41d0b824e82 0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97
0686e961-a90a-4f7f-a021-395b31157edf TriggeringRelationship 0b8b76e3-62fa-4527-9f05-2eb4dbaa8e97 1f487986-3cac-4af8-bda2-6400a1c71f48
ae8b3626-859f-4426-b9f0-4ab4921a2ba0 RealizationRelationship 40bec2d6-4545-48c2-acd5-089a05d4a723 14b2e8ce-cceb-4a72-a22b-1518ca582dfe
7acaaf00-bbc5-4944-993b-cdf6cafebc7b RealizationRelationship 40bec2d6-4545-48c2-acd5-089a05d4a723 fe7d7052-a3e5-4cea-a987-567e29fdf685
5e8733ec-990c-408d-ab01-732cfcd7c76e RealizationRelationship 40bec2d6-4545-48c2-acd5-089a05d4a723 ddc3713b-57ec-4152-8dc7-01b8166c969a
af4ba86f-3ab9-4996-a127-0ece6d1bca67 TriggeringRelationship 14b2e8ce-cceb-4a72-a22b-1518ca582dfe fe7d7052-a3e5-4cea-a987-567e29fdf685
296447fc-3601-44ec-9f16-0907edcfffc1 TriggeringRelationship fe7d7052-a3e5-4cea-a987-567e29fdf685 ddc3713b-57ec-4152-8dc7-01b8166c969a

Fetch complete objects including children using Golang and Gorm

I'm using Gorm and Golang to fetch data from my database. Is it possible to make Gorm fetch also the objects children (foreign keys)?
Database tables
users
+----+---------+------------+
| id | name | country_id |
+----+---------+------------+
| 1 | Adam | 1 |
| 2 | Bertil | 1 |
| 3 | Charlie | 2 |
+----+---------+------------+
countries
+----+--------+
| id | name |
+----+--------+
| 1 | Sweden |
| 2 | Norway |
+----+--------+
Models
type User struct {
Id int64 `json:"-"`
Name string `json:"name"`
CountryId int64 `json:"-"`
Country Country `json:"country"`
}
type Country struct {
Id int64 `json:"-"`
Name string `json:"name"`
}
Code to fetch all users
var users []User
DB.Find(&users) // Question: How should this be modified to automatically fetch the Country?
Actual result
[
{
"name": "Adam",
"country" : {
"name": "",
}
},
...
]
Desired result
[
{
"name": "Adam",
"country" : {
"name": "Sweden",
}
},
...
]
Thanks a lot for you input!
/Klarre
Yes it is possible, it's called Preloading.
users := make([]User,0)
DB.Preload("Country").Find(&users)

Laravel | Check that user belongs to all relationships BelongsToMany

I am trying to create a policy for updating a user to ensure that either the person updating or the user being updated belongs to a place.
I have the current database structure for the users
| id | first_name | last_name | email | password | created_at | updated_at |
and this is the places
| id | name | description | created_at | updated_at |
I then have a pivot table which is
| user_id | place_id |
Everything links up correctly and I can pass and associate data into each models.
What I am trying to achieve is that when I send in a request according to the JSON API spec which looks like the following:
{
"type": "users",
"attributes": {
...
},
"relationships": {
"places": {
"data": [
{
"type": "places",
"id": "1"
},
{
"type": "places",
"id": "2"
}
]
}
}
}
Inside of the updated policy, I want to check that either the authenticated user or the user being updated belongs to that place.
I have a method on the User model which is the following:
public function belongsToPlaces($placeIds)
{
return $this->places()->whereIn('id', $placeIds)->count() === count($placeIds);
}
This seems to work but it really doesn't feel very secure as realistically I should check each of the IDs. I'm just wondering if there is a built-in method to do this?
I would do a diff on the placeIds you already have with the one on the user. It will return all place ids there is not in the request, if it's not present on the users places. So check if the diff is empty, then everything is fine, otherwise the id's are invalid.
public function belongsToPlaces($placeIds)
{
return collect($placeIds)->diff($this->places()->pluck('id'))->isEmpty();
}

Update XMl based off CSV values using Powershell

I have a CSV file with the values as below:
Age , Status
29 , 0
41 , 1
44, 1
27, 0
60, 1
The XML is as below:
<office>
<staff branch="Torrance" Type="Implementation">
<employee>
<Name>Raj Parpani</Name>
<function>Implementation</function>
<age>29</age>
</employee>
<employee>
<Name>Kevin Woo</Name>
<function>Consultant</function>
<age>41</age>
</employee>
</staff>
<staff branch="Irvine" Type="Operations">
<employee>
<Name>David Woo</Name>
<function>Data</function>
<age>42</age>
</employee>
</staff>
</office>
If XML age is equal to the age in CSV, I have to append the status attribute for that age from the csv to the employee. I have tried the code as below:
ORIGINAL CODE
$csv = Import-Csv 'C:\Users\rparpani\Desktop\test2.csv' | Select-Object "Age","Status"
$xml = New-Object XML
$xml.Load("C:\Users\rparpani\Desktop\test.xml")
$nodes = $xml.SelectNodes("/office/staff/employee")
Foreach($row in $csv)
{
foreach($node in $nodes)
{
if($node.age -eq $row.age)
{
$node.SetAttribute("status", $row.Status);
}
}
}
Can someone please suggest how to change this to do what I want it to do
MODIFIED CODE
$csv = Import-Csv 'C:\Users\rparpani\Desktop\test2.csv' | Select-Object "Age","Status"
$xml = New-Object XML
$xml.Load("C:\Users\rparpani\Desktop\test.xml")
$nodes = $xml.SelectNodes("/office/staff/employee")
foreach($row in $csv) {
foreach($node in $nodes) {
if ($node.age -eq $row.age) {
if ($node.status) {
$node.status.innerText = $row.Status
}
else {
$status = $xml.CreateNode("element", "status", "")
$status.InnerText = $row.status
$node.AppendChild($status)
}
}
}
}
$xml.Save("C:\Users\rparpani\Desktop\test.xml")
Following code does what you are looking for.
You cannot use SetAttribute to create a new element with a value/InnerText. You need to create an element and append it to the node you are on. In your example xml, staff has two attributes, branch and Type that can be updated with SetAttribute method.
If Status already exists, update it with new value.. otherwise create a new element.
CSV Content
Age,Status
29,0
41,1
44,1
27,0
60,1
Script to add attribute to Node `Employee
foreach($row in $csv) {
foreach($node in $nodes) {
if ($node.age -eq $row.age) {
if ($row.status -eq "0") {
$node.SetAttribute("status", "Hired")
}
else {
$node.SetAttribute("status", "Fired")
}
}
}
}

How to define values specific to a connection of two nodes in GraphQL?

I have two types in my schema:
type Resident = { type Visitor = {
id id
name name
} }
In my database:
Residents and Visitors Tables:
+--------+-------+ +--------+---------+
| res_id | name | | vis_id | name |
+--------+-------+ +--------+---------+
| 1 | Alice | | 1 | Charlie |
| 2 | Bob | +--------+---------+
+--------+-------+
And then a table that shows which visitor belongs to which resident:
+--------+--------+--------------+
| res_id | vis_id | relationship |
+--------+--------+--------------+
| 1 | 1 | fam/fri |
| 2 | 1 | contractor |
+--------+--------+--------------+
Each visitor could either be a "fam/fri" or a "contractor" to a resident. So Charlie is Alice's visitor as her family or friend. However, Charlie is also a visitor to Bob, but instead as a contractor.
Question: How do I structure my schema so that when I query Alice, Charlie returns as a fam/fri, and when I query Bob, Charlie is returned as a contractor? I imagine this:
{
Resident(id: 1) { "Resident" {
name "Alice"
Visitor { "Visitor" {
id ===> "1"
name "Charlie"
relationship "fam/fri"
} }
} }
}
and also:
{
Resident(id: 2) { "Resident" {
name "Bob"
Visitor { "Visitor" {
id ===> "1"
name "Charlie"
relationship "contractor"
} }
} }
}
Something like:
type Query {
resident(id: Int): Resident
}
type Resident {
id: Int!
name: String!
visitors: [Visitor!]!
}
type Vistor {
id: Int!
name: String!
relationship: VisitorRelationship!
}
enum VisitorRelationship {
CONTRACTOR
FAMILY_OR_FRIEND
}
Note that by convention field names should be camelCase and type names should be in PascalCase. If the data returned from your data source (whether that's a database, API, or whatever) is not in the same shape as what you want to return from your GraphQL service, then you should transform the data before returning it inside your resolver, for example:
const relationshipMap = {
'fam/fri': 'FAMILY_OR_FRIEND',
'contractor': 'CONTRACTOR',
}
const resolvers = {
Query: {
resident: (root, args) => {
const resident = await Resident.findById(args.id)
// assuming resident has a property named joinTable that's
// an array and each relationship has a property named visitor
return {
...resident,
visitors: resident.joinTable.map(relationship => {
return {
...joinTable.visitor,
relationship: relationshipMap[joinTable.relationship],
}
})
}
},
},
}
You can also map enums to custom values this way.

Resources