Here is my question in brief:
I am using StrongLoop to work with an existing MySQL database. The database uses binary 16 datatypes to store primary keys and foreign keys. When I create the models using Strongloop tools, the data is sent to the client as string arrays in the JSON. I would like the JSON to contain the converted 36 character string. In the database, I have bintouuid and uuidtobin functions that will convert the data to/from the 36 character format. Can anyone provide the code I would use in the model or REST services to extend it to convert the arrays (or binary data) into the needed string format?
Here are details around the scenario:
The table script looks like this:
CREATE TABLE `alert` (
`ID` binary(16) NOT NULL,
`Subject` varchar(255),
`Text` text NOT NULL,
`Read` int(11) DEFAULT '0',
`AddedDate` timestamp NULL DEFAULT NULL,
`LastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`IsDeleted` bit(1) NOT NULL DEFAULT b'0',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
I have functions for creating and converting uuids to/from binary format:
newUuidToBin()
CREATE DEFINER=`root`#`localhost` FUNCTION `newuuidtobin`() RETURNS binary(16)
BEGIN
DECLARE UUID char(37);
SET UUID = UUID();
RETURN uuidtobin(UUID);
END
uuidToBin(UUID char(36))
CREATE DEFINER=`root`#`localhost` FUNCTION `uuidtobin`(UUID char(36)) RETURNS binary(16)
BEGIN
RETURN CONCAT(UNHEX(LEFT(UUID,8)),UNHEX(MID(UUID,10,4)),UNHEX(MID(UUID,15,4)),UNHEX(MID(UUID,20,4)),UNHEX(RIGHT(UUID,12)));
END
binToUuid(UUID BINARY(16))
CREATE DEFINER=`root`#`localhost` FUNCTION `bintouuid`(UUID BINARY(16)) RETURNS char(36) CHARSET utf8
BEGIN
RETURN concat(HEX(LEFT(uuid,4)),'-', HEX(MID(uuid,5,2)),'-', HEX(MID(uuid,7,2)),'-',HEX(MID(uuid,9,2)),'-',HEX(RIGHT(uuid,6)));
END
I have a trigger that creates the binary uuid when a record is created:
CREATE TRIGGER before_insert_alert
BEFORE INSERT
ON road.alert
FOR EACH ROW
SET new.id = newuuidtobin();
My default Alert.json for the model looks like this:
{
"name": "Alert",
"base": "PersistedModel",
"idInjection": false,
"mysql": {
"schema": "messaging",
"table": "alert"
},
"properties": {
"id": {
"type": "Binary",
"id": true,
"required": true,
"length": 16,
"precision": null,
"scale": null,
"mysql": {
"columnName": "ID",
"dataType": "binary",
"dataLength": 16,
"dataPrecision": null,
"dataScale": null,
"nullable": "N"
},
"_selectable": false
},
"subject": {
"type": "String",
"required": false,
"length": 65535,
"precision": null,
"scale": null,
"mysql": {
"columnName": "Subject",
"dataType": "text",
"dataLength": 65535,
"dataPrecision": null,
"dataScale": null,
"nullable": "Y"
},
"_selectable": true
},
"text": {
"type": "String",
"required": true,
"length": 255,
"precision": null,
"scale": null,
"mysql": {
"columnName": "Text",
"dataType": "varchar",
"dataLength": 255,
"dataPrecision": null,
"dataScale": null,
"nullable": "N"
},
"_selectable": false
},
"read": {
"type": "Number",
"required": false,
"length": null,
"precision": 10,
"scale": 0,
"mysql": {
"columnName": "Read",
"dataType": "int",
"dataLength": null,
"dataPrecision": 10,
"dataScale": 0,
"nullable": "Y"
},
"_selectable": true
},
"addeddate": {
"type": "Date",
"required": false,
"length": null,
"precision": null,
"scale": null,
"mysql": {
"columnName": "AddedDate",
"dataType": "timestamp",
"dataLength": null,
"dataPrecision": null,
"dataScale": null,
"nullable": "Y"
},
"_selectable": true
},
"lastupdated": {
"type": "Date",
"required": true,
"length": null,
"precision": null,
"scale": null,
"mysql": {
"columnName": "LastUpdated",
"dataType": "timestamp",
"dataLength": null,
"dataPrecision": null,
"dataScale": null,
"nullable": "N"
},
"_selectable": false
},
"isdeleted": {
"type": "Binary",
"required": true,
"length": null,
"precision": 1,
"scale": null,
"mysql": {
"columnName": "IsDeleted",
"dataType": "bit",
"dataLength": null,
"dataPrecision": 1,
"dataScale": null,
"nullable": "N"
},
"_selectable": false
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
When accessing the REST endpoint with a get,
http://localhost:3000/api/Alerts
...I get this result. Note: the id comes back in the form of an array.
[
{
"id": [
97,
55,
50,
102,
52,
49,
50,
48,
45,
57,
53,
54,
97,
45,
49,
49
],
"subject": "uuids",
"text": "my message",
"read": 0,
"addeddate": null,
"lastupdated": "2015-01-05T23:10:03.000Z",
"isdeleted": [
0
]
},
.
.
.
]
...but I want the result to look like this:
[
{
"id": "C39BC3A2-381F-5568-11C3-A0C2B66E64EF"
"subject": "uuids",
"text": "my message",
"read": 0,
"addeddate": null,
"lastupdated": "2015-01-05T23:10:03.000Z",
"isdeleted": [
0
]
},
.
.
.
]
On update, the REST endpoint should convert the string using the mysql function:
update alert set `read` = 1 where id = uuidtobin('C39BC3A2-381F-5568-11C3-A0C2B66E64EF');
How would I extend the model to use the mysql functions to select data showing the ids as uuid strings in the json result, and update records using the uuid 36 character string?
You can use a remote hook to manipulate the response before sending it back. See http://docs.strongloop.com/display/LB/Remote+hooks
Another possible solution is using model hooks to modify the data before/after saving it. See http://docs.strongloop.com/display/LB/Model+hooks
Related
I am new in NestJs TypeORM and I tried to get the count only from the relation table using loadRelationCountAndMap method and now I need a fetuare to change the order of that count ASC or DESC but when I tried the orderBy method it will return me unknow colunm name.
Here is my query
await this.userRepository
.createQueryBuilder('user')
.leftJoinAndSelect('user.roles', 'roles')
.loadRelationCountAndMap('user.postCount', 'user.post', 'post', qb =>
qb.where('post.type =:type', { type: 'post' }),)
.loadRelationCountAndMap('user.userSpotCount', 'user.spot', 'spot')
.loadRelationCountAndMap(
'user.itineraryCount',
'user.post',
'post',
qb => qb.where('post.type =:type', { type: 'itinerary' }),)
.where('roles.name = :name', { name: request.user_type })
.orderBy('userSpotCount', 'ASC');
and the output is without orderBy method
[{
"id": xxxxx,
"name": "xxxx xxxx",
"email": "xxxx.xxxx#xxxx.xxx",
"facebook_id": null,
"google_id": null,
"apple_id": null,
"is_email_verifie": null,
"is_phone_verifie": null,
"created_at": "2022-06-06T23:38:04.000Z",
"updated_at": "2022-06-06T23:38:04.000Z",
"phone": "1234567890",
"token": null,
"profile_pic": "",
"status": "pending",
"email_token": null,
"deleted_at": null,
"latitude": "26.78965",
"longitude": "93.78965",
"is_public": null,
"basedIn": null,
"visit_place": null,
"visit_place_lat": null,
"visit_place_long": null,
"notification_flag": "on",
"location": "abc, xyz, pqr",
"country_code": null,
"home_key": 1,
"postCount": 0,
"userSpotCount": 5,
"itineraryCount": 0
},
{
"id": xxxxx,
"name": "xxxx xxxx",
"email": "xxxx.xxxx#xxxx.xxx",
"facebook_id": null,
"google_id": null,
"apple_id": null,
"is_email_verifie": null,
"is_phone_verifie": null,
"created_at": "2022-06-06T23:38:04.000Z",
"updated_at": "2022-06-06T23:38:04.000Z",
"phone": "1234567890",
"token": null,
"profile_pic": "",
"status": "pending",
"email_token": null,
"deleted_at": null,
"latitude": "26.78965",
"longitude": "93.78965",
"is_public": null,
"basedIn": null,
"visit_place": null,
"visit_place_lat": null,
"visit_place_long": null,
"notification_flag": "on",
"location": "abc, xyz, pqr",
"country_code": null,
"home_key": 1,
"postCount": 0,
"userSpotCount": 1,
"itineraryCount": 0
}
]
I need this output as per the order by ASC/DESC
I have my first NodeJS API running. I have two API's now running (TEST and PROD).
These files are DIRECT copies of each other and running via App Manager in Cpanel.
Weirdly, one of the calls (Prod) is giving incorrect information on some of the calls... like it is giving 'old' data.
eg. a record was changed for an 'order' and a locationID was added to the database.
I have checked the database and it was added.
The test call:
https://www.myAPI.com.au/TEST/orders/myOrders/1709
Response:
{
"Result": true,
"order": {
"orderID": 1709,
"chemOrderID": 1243,
"firstName": "test",
"lastName": "test",
"phone": "04123456",
"email": null,
"prefContact": 1,
"itemName": "KN95 Box Of 30 ",
"itemQuantity": 1,
"plu": null,
"modelNumber": null,
"colour": null,
"itemDetails": null,
"supplier": "avacare",
"itemSize": null,
"amountPaid": 0,
"receiptNumber": "00",
"quotedPrice": 69.99,
"orderComments": null,
"reorder": 0,
"isNDIS": 0,
"isNDISPaid": 0,
"onHold": 0,
"requestedBy": 35,
"orderedBy": 35,
"receivedBy": 35,
"finalisedBy": 0,
"overdueBy": 0,
"NDISBy": 0,
"deletedBy": 0,
"requestedByName": "Jac",
"orderedByName": "Jac",
"receivedByName": "Jac",
"finalisedByName": null,
"overdueByName": null,
"deletedByName": null,
"requestedDateShort": "18 Jan",
"orderedDateShort": "18 Jan",
"receivedDateShort": "18 Jan",
"finalisedDateShort": null,
"overdueDateShort": null,
"deletedDateShort": null,
"requestedDate": "2022-01-18T09:40:21",
"orderedDate": "2022-01-18T09:50:33",
"receivedDate": "2022-01-18T12:21:41",
"finalisedDate": null,
"overdueDate": null,
"deletedDate": null,
"etaMaxDateShort": "Thu, 20 Jan",
"etaCode": 2,
"locationID": 199,
"supplierRef": null,
"locationOther": null,
"categoryID": 5,
"categoryName": "GENERAL SHOP"
}
}
Now this is correct. The locationID is updated, the receivedDate, recivedByName and receivedBy are all correct and updated.
The same call on copied API: (same mysql user login. literally a duplicate of the api)
Call:
https://www.myAPI.com.au/prod/orders/myOrders/1709
Response:
{
"Result": true,
"order": {
"orderID": 1709,
"chemOrderID": 1243,
"firstName": "test",
"lastName": "test",
"phone": "04123456",
"email": null,
"prefContact": 1,
"itemName": "KN95 Box Of 30 ",
"itemQuantity": 1,
"plu": null,
"modelNumber": null,
"colour": null,
"itemDetails": null,
"supplier": "avacare",
"itemSize": null,
"amountPaid": 0,
"receiptNumber": "00",
"quotedPrice": 69.99,
"orderComments": null,
"reorder": 0,
"isNDIS": 0,
"isNDISPaid": 0,
"onHold": 0,
"requestedBy": 35,
"orderedBy": 35,
"receivedBy": 0,
"finalisedBy": 0,
"overdueBy": 0,
"NDISBy": 0,
"deletedBy": 0,
"requestedByName": "Jac",
"orderedByName": "Jac",
"receivedByName": null,
"finalisedByName": null,
"overdueByName": null,
"deletedByName": null,
"requestedDateShort": "18 Jan",
"orderedDateShort": "18 Jan",
"receivedDateShort": null,
"finalisedDateShort": null,
"overdueDateShort": null,
"deletedDateShort": null,
"requestedDate": "2022-01-18T09:40:21",
"orderedDate": "2022-01-18T09:50:33",
"receivedDate": null,
"finalisedDate": null,
"overdueDate": null,
"deletedDate": null,
"etaMaxDateShort": "Thu, 20 Jan",
"etaCode": 2,
"locationID": null,
"supplierRef": null,
"locationOther": null,
"categoryID": 5,
"categoryName": "GENERAL SHOP"
}
}
As can be seen, the aforementioned fields aren't filled!?
It's like the call is getting an old version of the database or something...
I can't understand this at all.
There is only one DB, i haven't created a test db, in reality this whole thing is testing (even the prod version), as I am learning and trying to understand how I will go about everything once it is actually live.
I am total newbie in JMESPath parsing.
az network lb inbound-nat-rule list --resource-group MYRG --lb-name MYLB is returning below output and I would like filter only backendIpConfiguration.id and backendPort in the response.
Below response in have array of elements.
[
{
"backendIpConfiguration": {
"applicationGatewayBackendAddressPools": null,
"applicationSecurityGroups": null,
"etag": null,
"gatewayLoadBalancer": null,
"id": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"loadBalancerBackendAddressPools": null,
"loadBalancerInboundNatRules": null,
"name": null,
"primary": null,
"privateIpAddress": null,
"privateIpAddressVersion": null,
"privateIpAllocationMethod": null,
"privateLinkConnectionProperties": null,
"provisioningState": null,
"publicIpAddress": null,
"resourceGroup": "MYRG01",
"subnet": null,
"type": null,
"virtualNetworkTaps": null
},
"backendPort": 1367,
"enableFloatingIp": false,
"enableTcpReset": false,
"etag": "W/\"XXXXX-1173-49ad-8d1f-40347c00d88a\"",
"frontendIpConfiguration": {
"id": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"resourceGroup": "MYRG01"
},
"frontendPort": 1367,
"id": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"idleTimeoutInMinutes": 5,
"name": "rule1",
"protocol": "Tcp",
"provisioningState": "Succeeded",
"resourceGroup": "MYRG01",
"type": "Microsoft.Network/loadBalancers/inboundNatRules"
},
{
"backendIpConfiguration": {
"applicationGatewayBackendAddressPools": null,
"applicationSecurityGroups": null,
"etag": null,
"gatewayLoadBalancer": null,
"id": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"loadBalancerBackendAddressPools": null,
"loadBalancerInboundNatRules": null,
"name": null,
"primary": null,
"privateIpAddress": null,
"privateIpAddressVersion": null,
"privateIpAllocationMethod": null,
"privateLinkConnectionProperties": null,
"provisioningState": null,
"publicIpAddress": null,
"resourceGroup": "MYRG02",
"subnet": null,
"type": null,
"virtualNetworkTaps": null
},
"backendPort": 3006,
"enableFloatingIp": false,
"enableTcpReset": false,
"etag": "W/\"XXXX-1173-49ad-8d1f-40347c00d88a\"",
"frontendIpConfiguration": {
"id": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"resourceGroup": "MYRG02"
},
"frontendPort": 3006,
"id": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"idleTimeoutInMinutes": 5,
"name": "rule2",
"protocol": "Tcp",
"provisioningState": "Succeeded",
"resourceGroup": "MYRG02",
"type": "Microsoft.Network/loadBalancers/inboundNatRules"
}
]
Filtering in JMESPath is quite simple, and the documentation is pretty straight forward for filters and multiselect hashes.
In here, a simple query like:
[].{backendIpConfigurationId: backendIpConfiguration.id, backendPort: backendPort}
Will give you the filtered JSON:
[
{
"backendIpConfigurationId": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"backendPort": 1367
},
{
"backendIpConfigurationId": "/subscriptions/XXXX/XXX/XXX/providers/Microsoft.Network/networkInterfaces/XXX/ipConfigurations/XXXX",
"backendPort": 3006
}
]
Containing only the informations you are looking for.
I'm trying to retrieve a given number of values from the following json object (just used 2 for brevity):
[
{
"content": null,
"deleted": false,
"metadata": null,
"name": "name/windows-2016-osDisk.170b8936-d66d-4139-a409-26f4e9d354fe.vhd",
"properties": {
"appendBlobCommittedBlockCount": null,
"blobTier": "P10",
"blobTierChangeTime": null,
"blobTierInferred": true,
"blobType": "PageBlob",
"contentLength": 136367309312,
"contentRange": null,
"contentSettings": {
"cacheControl": null,
"contentDisposition": null,
"contentEncoding": null,
"contentLanguage": null,
"contentMd5": "-0q970378r08==",
"contentType": "application/octet-stream"
},
"copy": {
"completionTime": null,
"id": null,
"progress": null,
"source": null,
"status": null,
"statusDescription": null
},
"creationTime": "2019-11-21T08:34:33+00:00",
"deletedTime": null,
"etag": "0237502375",
"lastModified": "2019-11-21T08:34:33+00:00",
"lease": {
"duration": null,
"state": "available",
"status": "unlocked"
},
"pageBlobSequenceNumber": null,
"remainingRetentionDays": null,
"sequenceNumber": 1,
"serverEncrypted": true
},
"snapshot": null
},
{
"content": null,
"deleted": false,
"metadata": null,
"name": "name/windows-2019-osDisk.f122fb3c-0edb-42a8-b98c-56657b447f15.vhd",
"properties": {
"appendBlobCommittedBlockCount": null,
"blobTier": "P10",
"blobTierChangeTime": null,
"blobTierInferred": true,
"blobType": "PageBlob",
"contentLength": 136367309312,
"contentRange": null,
"contentSettings": {
"cacheControl": null,
"contentDisposition": null,
"contentEncoding": null,
"contentLanguage": null,
"contentMd5": "0237502375/hKOg==",
"contentType": "application/octet-stream"
},
"copy": {
"completionTime": null,
"id": null,
"progress": null,
"source": null,
"status": null,
"statusDescription": null
},
"creationTime": "2019-11-21T08:35:03+00:00",
"deletedTime": null,
"etag": "20397520i3h523",
"lastModified": "2019-11-21T08:35:03+00:00",
"lease": {
"duration": null,
"state": "available",
"status": "unlocked"
},
"pageBlobSequenceNumber": null,
"remainingRetentionDays": null,
"sequenceNumber": 1,
"serverEncrypted": true
},
"snapshot": null
}
]
I sort this on creationTime in jq like so: jq 'sort_by(.properties.creationTime)' When I pipe this through | .[].name making jq 'sort_by(.properties.creationTime) | .[].name I get a sorted list of the names.
My question is: How can I pass an integer to this command and remove these many names, starting from the most recent created (bottom)?
following
https://stedolan.github.io/jq/manual/v1.6/#Builtinoperatorsandfunctions
slicing should work:
jq 'sort_by(.properties.creationTime) | .[-1:]'
The answer I've used is the following:
jq 'sort_by(.properties.creationTime) | .[-4:] | .[].name'
Where -4 is the amount of names to display starting from the bottom.
I have this items in a JSON file that I need to compare wherever I have Curr or Prev values and compare if they are equals. this algorithm is with angular 5 but I'm being unable to do this, I did the load function with httpClient
Example :
[{
"id": 1,
"comparisonDate": "2017-06-22",
"milestone": "CURR_PREV",
"udDomain": "BASIS",
"udIdentifier": "332A251000.01",
"rpt": "D70",
"approvedCurr": true,
"approvedPrev": null,
"commercialReferenceCurr": "BASIS - 01.01.2007",
"commercialReferencePrev": null,
"customizationImpactCurr": null,
"customizationImpactPrev": null,
"deliveryTypeCurr": null,
"deliveryTypePrev": null,
"aircraftId": 184,
"aircraftSapId": "580652",
"aircraftName": "BUL 011",
"aircraftSerialNumber": "02713",
"quantityCurr": "1",
"quantityPrev": null,
"statusCurr": "O",
"statusPrev": null,
"typeModification": "CREATION",
"validityCurr": "V",
"validityPrev": null
}, {
"id": 2,
"comparisonDate": "2017-06-22",
"milestone": "CURR_PREV",
"udDomain": "BASIS",
"udIdentifier": "332A270028.01",
"rpt": "E15",
"approvedCurr": true,
"approvedPrev": null,
"commercialReferenceCurr": "BASIS - 01.01.2007",
"commercialReferencePrev": null,
"customizationImpactCurr": null,
"customizationImpactPrev": null,
"deliveryTypeCurr": null,
"deliveryTypePrev": null,
"aircraftId": 184,
"aircraftSapId": "580652",
"aircraftName": "BUL 011",
"aircraftSerialNumber": "02713",
"quantityCurr": "1",
"quantityPrev": null,
"statusCurr": "O",
"statusPrev": null,
"typeModification": "CREATION",
"validityCurr": "V",
"validityPrev": null
}]
this should be with using lodash.
i assume your want something like this
for each object in your array
filter keys that end with "Curr"
for each get Prev property
compare it with curr property
let obj = [{
"id": 1,
"comparisonDate": "2017-06-22",
"milestone": "CURR_PREV",
"udDomain": "BASIS",
"udIdentifier": "332A251000.01",
"rpt": "D70",
"approvedCurr": true,
"approvedPrev": null,
"commercialReferenceCurr": "BASIS - 01.01.2007",
"commercialReferencePrev": null,
"customizationImpactCurr": null,
"customizationImpactPrev": null,
"deliveryTypeCurr": null,
"deliveryTypePrev": null,
"aircraftId": 184,
"aircraftSapId": "580652",
"aircraftName": "BUL 011",
"aircraftSerialNumber": "02713",
"quantityCurr": "1",
"quantityPrev": null,
"statusCurr": "O",
"statusPrev": null,
"typeModification": "CREATION",
"validityCurr": "V",
"validityPrev": null
}, {
"id": 2,
"comparisonDate": "2017-06-22",
"milestone": "CURR_PREV",
"udDomain": "BASIS",
"udIdentifier": "332A270028.01",
"rpt": "E15",
"approvedCurr": true,
"approvedPrev": null,
"commercialReferenceCurr": "BASIS - 01.01.2007",
"commercialReferencePrev": null,
"customizationImpactCurr": null,
"customizationImpactPrev": null,
"deliveryTypeCurr": null,
"deliveryTypePrev": null,
"aircraftId": 184,
"aircraftSapId": "580652",
"aircraftName": "BUL 011",
"aircraftSerialNumber": "02713",
"quantityCurr": "1",
"quantityPrev": null,
"statusCurr": "O",
"statusPrev": null,
"typeModification": "CREATION",
"validityCurr": "V",
"validityPrev": null
}];
obj.forEach(x=>{
Object.keys(x)
.filter(y=>y.endsWith("Curr"))
.forEach(y=>{
let prevProp = y.replace("Curr", "Prev")
console.log(y, x[y]);
console.log(prevProp ,x[prevProp ]);
if(x[y]===x[prevProp ]){
//equal
}else{
//not equal
}
})
})
you could use lodash's _.forEach, _.Keys, _.filter but i think there is not much point on this.