Retain trailing 's' for table in Postgraphile - postgraphile

Is there a way to disable the 'remove-the-plural-s' feature in Postgraphile?
I have a table OS in my database and am using the very awesome Postgraphile library to create a GraphQL interface for free. Everything is great, but Postgraphile is truncating my table name, thinking it is plural. So I get allOs instead of allOses and createO, updateO, etc...
I tried:
Adding an underscore after the table name, and then it just retains the entire thing with an underscore.
Adding an underscore (O_S) and then the plural has capital-s allOS but the singular is O_
A smart comment specifying E'#name os' but it still drops the s
A smart comment specifying E'#name oss' which then pluralizes correctly allOsses (haha) and keeps both for the singular oss
PS in case you see this Benjie/other contributors, your documentation is incredible and the library will save me months of work.

This change is performed by PostGraphile's inflector; however it doesn't always get it right (e.g. in this case) but fortunately it's possible to override it with a small plugin.
In this case, it's probably best to add specific exceptions to the pluralize and singularize functions; you can do this using makeAddInflectorsPlugin from our inflection system. Be sure to pass true as the second argument so that the system knows you're deliberately overwriting the inflectors.
const { makeAddInflectorsPlugin } = require('graphile-utils');
module.exports = makeAddInflectorsPlugin(oldInflectors => ({
pluralize(str) {
if (str.match(/^os$/i)) {
return str + 'ses';
}
return oldInflectors.pluralize(str);
},
singularize(str) {
if (str.match(/^osses$/i) {
return str.substr(0, 2);
}
return oldInflectors.singularize(str);
}
}), true);
I'm glad you're enjoying PostGraphile 🤘

Related

How to access the key of a jsoncpp Value

I kind of feel stupid for asking this, but haven't been able to find a way to get the key of a JSON value. I know how to retrieve the key if I have an iterator of the object. I also know of operator[].
In my case the key is not a known value, so can't use get(const char *key) or operator[]. Also can't find a getKey() method.
My JSON looks like this:
{Obj_Array: [{"122":{"Member_Array":["241", "642"]}}]}
For the piece of code to parse {"122":{"Member_Array":["241", "642"]}} I want to use get_key()-like function just to retrieve "122" but seems like I have to use an iterator which to me seems to be overkill.
I might have a fundamental lack of understanding of how jsoncpp is representing a JSON file.
First, what you have won't parse in JsonCPP. Keys must always be enclosed in double quotes:
{"Obj_Array": [{"122":{"Member_Array":["241", "642"]}}]}
Assuming that was just an oversight, if we add whitespace and tag the elements:
{
root-> "Obj_Array" : [
elem0-> {
key0-> "122":
val0-> {
key0.1-> "Member_Array" :
val0.1-> [
elem0.1.0-> "241",
elem0.1.1-> "642" ]
}
}
]
}
Assuming you have managed to read your data into a Json::Value (let's call it root), each of the tagged values can be accessed like this:
elem0 = root[0];
val0 = elem0["122"]
val0_1 = val0["Member_Array"];
elem0_1_0 = val0_1[0];
elem0_1_1 = val0_1[1];
You notice that this only retrieves values; the keys were known a priori. This is not unusual; the keys define the schema of the data; you have to know them to directly access the values.
In your question, you state that this is not an option, because the keys are not known. Applying semantic meaning to unknown keys could be challenging, but you already came to the answer. If you want to get the key values, then you do have to iterate over the elements of the enclosing Json::Value.
So, to get to key0, you need something like this (untested):
elem0_members = elem0.getMemberNames();
key0 = elem0_members[0];
This isn't production quality, by any means, but I hope it points in the right direction.

Implement CSV download using current filters and sort

I need to implement a download feature. It will read the data in the react-data-grid (adazzle), respecting the current columns, filters and sort, and create an array json (or comma separated strings) I can then pass to the react-csv module.
I have a data structure populated from the backend but it is not filtered nor sorted. I need to be able to ask the grid for it's data on a row-by-row basis. Can anyone point me in the right direction?
Without code or some context, I can't answer with certainty...
You supply the rowGetter prop with the collection to display, or the method to get the rows to display...I'm thinking if you filtering, then most likely you've got some sort of mechanism supporting that... Either way, you can use this property's value somehow to get exactly what you see in the grid.
If you literally want to interrogate the grid, you could try adding a reference to the grid, and then see if you can ask it for the row data. I can't remember with certainty that I saw a rows prop in the grids available props via the ref, but I imagine you should be able to (**,)
...
handleExport = async => {
const exportRows = rows;
// const exportRows = getRows(initialRows, filters);
// const exportRows = this.state.gridref.CurrentRows DISCLAIMER:CurrentRows is just for giving the idea... check out the ref yourself to see if it's possible to get the rows via the grid refs props.
downloadCSV( exportRows )
}
...
<ReactDataGrid
ref={input => {this.state.gridref = input}}
columns={columns}
rowGetter={i => rows[i]} // or maybe rowGetter={i => getRows(initialRows, filters)[i]}
rowsCount={rows.length}
onGridSort={(sortColumn, sortDirection) =>
setRows(sortRows(initialRows, sortColumn, sortDirection))
}
/>
I've only ever [set / initialised] the this.state.gridRef prop in my constructor, but I guess you could also [set / initialise] it in your componentDidMount as well...
initialise like this:
this.state.gridRef = React.createRef()

JSONPath Syntax when dot in key

Please forgive me if I use the incorrect terminology, I am quite the novice.
I have some simple JSON:
{
"properties": {
"footer.navigationLinks": {
"group": "layout"
, "default": [
{
"text": "Link a"
, "href": "#"
}
]
}
}
}
I am trying to pinpoint "footer.navigationLinks" but I am having trouble with the dot in the key name. I am using http://jsonpath.com/ and when I enter
$.properties['footer.navigationLinks']
I get 'No match'. If I change the key to "footernavigationLinks" it works but I cannot control the key names in the JSON file.
Please can someone help me target that key name?
Having a json response:
{
"0": {
"SKU": "somevalue",
"Merchant.Id": 234
}
}
I can target a key with a . (dot) in the name.
jsonPath.getJsonObject("0.\"Merchant.Id\"")
Note: the quotes and the fact that they are escaped.
Note not sure of other versions, but I'm using
'com.jayway.restassured', name: 'json-path', version: '2.9.0'
A few samples/solutions I've seen, was using singe quotes with brackets, but did not work for me.
For information, jsonpath.com has been patched since the question was asked, and it now works for the example given in the question. I tried these paths successfully:
$.properties['footer.navigationLinks']
$.properties.[footer.navigationLinks]
$.properties.['footer.navigationLinks']
$['properties']['footer.navigationLinks']
$.['properties'].['footer.navigationLinks']
properties.['footer.navigationLinks']
etc.
This issue was reported in 2007 as issue #4 - Member names containing dot fail and fixed.
The fix is not present in this online jsonpath.com implementation, but it is fixed in this old archive and probably in most of the forks that have been created since (like here and here).
Details about the bug
A comparison between the buggy and 2007-corrected version of the code, reveals that the correction was made in the private normalize function.
In the 2007-corrected version it reads:
normalize: function(expr) {
var subx = [];
return expr.replace(/[\['](\??\(.*?\))[\]']|\['(.*?)'\]/g, function($0,$1,$2){
return "[#"+(subx.push($1||$2)-1)+"]";
}) /* http://code.google.com/p/jsonpath/issues/detail?id=4 */
.replace(/'?\.'?|\['?/g, ";")
.replace(/;;;|;;/g, ";..;")
.replace(/;$|'?\]|'$/g, "")
.replace(/#([0-9]+)/g, function($0,$1){
return subx[$1];
});
},
The first and last replace in that sequence make sure the second replace does not interpret a point in a property name as a property separator.
I had a look at the more up-to-date forks that have been made since then, and the code has evolved enormously since.
Conclusion:
jsonpath.com is based on an outdated version of JSONPath and is not reliable for previewing what current libraries would provide you with.
You can encapsulate the 'key with dots' with single quotes as below
response.jsonpath().get("properties.'footer.navigationLinks'")
Or even escape the single quotes as shown:
response.jsonpath().get("properties.\'footer.navigationLinks\'")
Both work fine

how to read/interpret json file to define mysql schema

I have been tasked with mapping a json file to a mysql database and I am trying to define the appropriate schema a sample of the json file is below
"configurationItems":[
{
"ARN":"",
"availabilityZone":"",
"awsAccountId":"hidden from sight ",
"awsRegion":"",
"configuration":{
"amiLaunchIndex":,
"architecture":"",
"blockDeviceMappings":[
{
"deviceName":"",
"ebs":{
"attachTime":"",
"deleteOnTermination":true,
"status":"attached",
"volumeId":""
}
}
],
"clientToken":"",
"ebsOptimized":,
"hypervisor":"",
"imageId":"",
"instanceId":"",
"instanceType":"",
"kernelId":"aki-",
"keyName":"",
"launchTime":"",
"monitoring":{
"state":""
},
"networkInterfaces":[
{ etc
am I right in thinking that the way to do this is essentially wherever there is a bracket /child element there would be a new table eg; configuration items down to aws region would be in a table then configuration through architecture followed by block device mappings etc etc if that is the case then where would the client token through lanch time belong ? many thanks in advance folks
That certainly is a way to use it.
It gives a more parent child relation approach to the setup.
E.g.
"blockDeviceMappings":[
{
"deviceName":"/dev/sda1",
"ebs":{
"attachTime":"2014-01-06T10:37:40.000Z",
"deleteOnTermination":true,
"status":"attached",
"volumeId":""
}
}
]
Probably could have more than one devices so it would be a 1 to many relation.

reactivemongo - merging two BSONDocuments

I am looking for the most efficient and easy way to merge two BSON Documents. In case of collisions I have already handlers, for example if both documents include Integer, I will sum that, if a string also, if array then will add elements of the other one, etc.
However due to BSONDocument immutable nature it is almost impossible to do something with it. What would be the easiest and fastest way to do merging?
I need to merge the following for example:
{
"2013": {
"09": {
value: 23
}
}
}
{
"2013": {
"09": {
value: 13
},
"08": {
value: 1
}
}
}
And the final document would be:
{
"2013": {
"09": {
value: 36
},
"08": {
value: 1
}
}
}
There is a method in BSONDocument.add, however it doesn't check uniqueness, it means I would have at the end 2 BSON documents with "2013" as a root key, etc.
Thank you!
If I understand you inquiry, you are looking to aggregate field data via composite id. MongoDB has a fairly slick aggregate framework. Part of that framework is the $group pipeline aggregate keyword. This will allow you to specify and _id to group by which could be defined as a field or a document as in your example, as well as perform aggregation using accumulators such as $sum.
Here is a link to the manual for the operators you will probably need to use.
http://docs.mongodb.org/manual/reference/operator/aggregation/group/
Also, please remove the "merge" tag from your original inquiry to reduce confusion. Many MongoDB drivers include a Merge function as part of the BsonDocument representation as a way to consolidate two BsonDocuments into a single BsonDocument linearly or via element overwrites and it has no relation to aggregation.
Hope this helps.
ndh