express-graphql: How to remove external "data" object layer. - express

I am replacing an existing REST endpoint with GraphQL.
In our existing REST endpoint, we return a JSON array.
[{
"id": "ABC"
},
{
"id": "123"
},
{
"id": "xyz"
},
{
"id": "789"
}
]
GraphQL seems to be wrapping the array in two additional object layers. Is there any way to remove the "data" and "Client" layers?
Response data:
{
"data": {
"Client": [
{
"id": "ABC"
},
{
"id": "123"
},
{
"id": "xyz"
},
{
"id": "789"
}
]
}
}
My query:
{
Client(accountId: "5417727750494381532d735a") {
id
}
}

No. That was the whole purpose of GraphQL. To have a single endoint and allow users to fetch different type/granularity of data by specifying the input in a query format as opposed to REST APIs and then map them onto the returned JSON output.
'data' acts as a parent/root level container for different entities that you have queried. Without these keys in the returned JSON data, there won't be any way to segregate the corresponding data. e.g.
Your above query can be modified to include another entity like Owner,
{
Client(accountId: "5417727750494381532d735a") {
id
}
Owner {
id
}
}
In which case, the output will be something like
{
"data": {
"Client": [
...
],
"Owner": [
...
]
}
}
Without the 'Client' and 'Owner' keys in the JSON outout, there is no way to separate the corresponding array values.
In your case, you can get only the array by doing data.Client on the returned output.

Related

Can't make PUT /raylight/v1/documents/id/parameter/id work properly

I need to update document parameters via REST API.
I've tried using the following:
PUT .../raylight/v1/documents/33903/parameters/3
with the following json payload
{
"parameters":{
"parameter": {
"id": 3,
"answer": {
"values": {
"value": [
"2019/9"
]
}
}
}
}
}
But the returned answer shows unmodified parameters:
{
"parameter": {
"#optional": "false",
"#type": "prompt",
...
"id": 3,
...
"answer": {
...
"info": {
...
"previous": {
"value": [
"2015\/12"
]
}
},
"values": {
"value": [
"2015\/12"
]
}
}
}
}
How can I properly set new prompt parameters?
Do:
PUT .../raylight/v1/documents/33903/parameters
instead of:
PUT .../raylight/v1/documents/33903/parameters/3
Adding a parameter ID at the end performs a different function: it returns the list of parameters that are dependent upon the one provided. You have only one in this case, and it's returning itself. Leave it off, to refresh the document.

JSON Schema: Can I use "if" deeper than root of schema?

I want to validate objects like this
{
type: "user",
data: {id: 1},
}
and
{
type: "account",
data: {uuid: "xxxx"},
}
I thought I can write schema like this
{
type: "object",
properties: {
type: {enum: ["user", "account"]},
data: {
"if": {properties: {type: {const: "user"}}},
"then": {
type: "object",
properties: {
id: {type: "number"}
}
},
"else": {
type: "object",
properties: {
uuid: {type: "string"}
}
},
}
}
}
but it looks like I can't refer to root type field from context of data field. So I have two questions. Can I use if deeper than root? If I can then how to refer to parent or root object from nested object? I'm using node ajv for validation.
You're correct, you cannot apply validation to a different part of your data than where your subschems is being applied. Let me explain a little.
The first thing that happens when processing a JSON Schema is the Schema as a whole is "applied" to the instance as a whole.
properties is an applicator keyword, in that it doesn't assert any validation rules by itself. The VALUES of a properties object are subschemas (which are Schemas in their own right) which are APPLIED to the instance location value when the associated KEY matches.
To give you an exanple, in your Schema, the subschema at properties > type is applied to instance location type, which means the VALUE of the object key type. If type didn't exist in your data, the subschema in your Schema wouldn't do anything (it wouldn't be applied anywhere).
This is broadly the processing model of a Schema against an instance. Hopefully this explains why you can't work in the way you're expecting. However it's still possible to achive what you want.
then and else are conditional applicator keywords, and so need to be applied following the same model.
What you need to do is use if, then, else at the top level, but have deep / nested application of the validation you want to do.
Here's a demo with a new Schema and instance
https://jsonschema.dev/s/sejHF
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"type": {
"enum": [
"user",
"account"
]
},
"data": {}
},
"if": {
"properties": {
"type": {
"const": "user"
}
}
},
"then": {
"type": "object",
"properties": {
"data": {
"properties": {
"id": {
"type": "number"
}
}
}
}
},
"else": {
"type": "object",
"properties": {
"data": {
"properties": {
"uuid": {
"type": "string"
}
}
}
}
}
}
If you also want to make sure that id is present when type is user, then you also need to add required: ['id'] in the then subschema. (You'll need to do similar in the else clause if you want to check for uuid too.

Validating that a property value exists withing the keys of an object

Wise crowd,
I already have a working JSON Schema (v0.7) to validate my data. This is an example of valid JSON:
{
"people": [
{ "id": 1, "name": "bob" },
...
]
}
Now I need to a bunch of strings in it:
{
"people": [
{ "id": 1, "name": "bob", "appears_in": "long_string_id_1" },
{ "id": 2, "name": "ann", "appears_in": "long_string_id_1" }
...
],
"long_strings": {
"long_string_id_1": "blah blah blah.....",
...
}
}
What I need is:
a value for key appears_in MUST be a key of the long_strings object
(optional) a key of the long_strings object MUST be used as value in on of the appears_in key
Property dependencies are nice, but don't seem to address my needs.
Any idea?
And this question is not a duplicate, because I do not know the values in advance.
Sorry. You cannot do this in JSON schema. You cannot reference data in your schema.

RestKit Mapping concatenate

I have some json like this :
{
"items": [
{
"datas": [
{
"date": "2015-01-20T00:00+0100"
},
{
"date": "2015-01-21T00:00+0100"
}
],
"id": "100"
},
{
"datas": [
{
"date": "2015-01-20T00:00+0100"
},
{
"date": "2015-01-21T00:00+0100"
}
],
"id": "200"
}
],
"id": "itemset1"
}
I have an Object, data, with some info and a date.
I would like to set a property identifier to a value composed with the parent id and the date, like 100_2015-01-20T00:00+0100
I can get the parent id in my identifier with the following code :
[dataMapping addAttributeMappingsFromDictionary:#{"#parent.id":#"identifier",...}];
Is they a way do concatenate value with RestKit mapping?
You can't concatenate directly, no. Instead you would store both of the attributes and provide a public method which concatenates and returns the value. Or perhaps set the variables to transient and on willSave (or similar) convert them and persistently store the concatenated value.

Can Elasticsearch make suggestions for mapping?

Playing around with Elasticsearch I added a document to my index called "pets", that looks like this:
{
"name" : "Piper",
"type" : "dog"
}
Then I added a second document:
{
"name" : "Max",
"type" : "dog",
"breed": "Scottish Terrier"
}
Now, I understand that the mapping of my "pets" index is initially created based on my first document ( unless i define a mapping at some point ). However, I am curious to know if ES can suggest a mapping based on the existing data ( like MySQL's "Propose table structure" ) or maybe update the mapping automatically.
Yes, ElasticSearch will automatically update the mapping.
Sometimes the language in the ElasticSearch documentation makes it sound like once the mapping is set, it cannot be changed. This is only true for the existing fields. Any additional fields will be automatically assigned a type and added to the mapping.
Remember you can always check the mapping of an index with the get mapping API:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-mapping.html
For example, with the example you have above, after your first "pet" document the mapping is:
{
"my_index": {
"mappings": {
"pet": {
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
}
}
}
}
And after the second "pet" document, your mapping is:
{
"my_index": {
"mappings": {
"pet": {
"properties": {
"breed": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
}
}
}
}
I'm not familiar with MySQL's propose table structure, so I can't comment on that...