Mapping relationships where the JSON representation can hold either a nested object or an object ID (in RestKit) - restkit

Is it possible to get RestKit to properly map relationships where the property might contain either a nested object or an object ID?
The API I'm currently working with often returns deep cyclical object graphs where multiple occurrences of the same object are replaced with the object's ID.
A simple example:
Nested
[
{
id: 1,
title: "Post Title",
category: {
id: 1,
name: "Category Title"
}
},
{
id: 2,
title: "Post Title",
category: 1
}
]
Since the replacement can happen at any level manually fixing the JSON before mapping is not very practical.

Related

GraphQL, extract all values of a specific type into an array

Let's assume I have schema like
type StaticData {
id: Int!
language: String!
name: String!
description: String!
someA: SpecialType!
someB: SpecialType!
}
SpecialType is a scalar. SpecialType can be used in further nested structures as well. Let's now assume I query for a list of StaticData. Is it somehow possible to receive a list of all SpecialType values, without me extracting it manually from the returned object?
Example:
My return object looks like this:
[
{
id: 1,
language: 'en',
name: 'Something',
description: 'SomeDescription',
someA: 1234,
someB: 2345
},
{
id: 2,
language: 'en',
name: 'SomethingElse',
description: 'SomeDescription',
someA: 4564,
someB: 1234
},
]
Since I want all SpecialType values, I do want to extract [1234, 2345, 4564, 1234]. Maybe it is possible to do the extraction on the server using resolvers and receive it with the full result object?
If you want the GraphQL response to be just a list of integers, then you'll need to provide a type of that shape to your schema, i.e. someA: [SpecialType!].
You're on the right track - it's on you to then build and return a list in the resolver that satisfies this structure. Hope this helps!

GraphQL/Netlify CMS - don't error if query field is undefined (doesn't exist)

I'm using Gatsby with Netlify CMS and have some optional fields in a file collection. The problem with this is that I'm unable to retrieve these fields using GraphQL, as the field doesn't exist if it was left blank.
For example, let's say I have the following collection file:
label: "Primary Color",
name: "primary",
file: "data/palette.yaml",
widget: "object",
fields: [
{
label: "Light",
name: "light",
required: false,
widget: "string"
},
{
label: "Main",
name: "main",
required: false,
widget: "string"
},
{
label: "Dark",
name: "dark",
required: false,
widget: "string"
},
{
label: "Contrast Text",
name: "contrastText",
required: false,
widget: "string"
}
]
All fields are optional. So let's say the user only enters in a value for main. This then saves the data as:
primary:
main: '#ff0000'
light, dark and contrastText are not saved at all - they are simply left out entirely.
When I query the data in GraphQL, I obviously need to check for ALL fields since I have no idea which optional fields were filled in by the user and which were left blank. This means my query should be something like:
query MyQuery {
paletteYaml {
primary {
light
main
dark
contrastText
}
}
}
Using the above example where the user only filled in the main field, the above query will throw an error as light, dark and contrastText fields do not exist.
I am using a file collection type (as opposed to folder collection type) for this, so I can't set a default value. It wouldn't matter if I could set a default value anyway, since GraphQL and Yaml do not accept undefined as a value - they can only accept null or an empty string ("") as a best alternative.
Even if I manually save the yaml file with all field values set to null or "", this wouldn't work either as it would then cause additional issues as I am deep merging the query result with another javascript object.
I simply need to have GraphQL return undefined for each blank (missing) field instead of throwing an error, or not return the blank/missing fields at all.
This seems like a common issue (handling optional fields in Netlify CMS) but there is nothing in the documentation about it. How do people handle this issue?

How could I structure my graphql schema to allow for the retrieval of possible dropdown values?

I'm trying to get the possible values for multiple dropdown menus from my graphQL api.
for example, say I have a schema like so:
type Employee {
id: ID!
name: String!
jobRole: Lookup!
address: Address!
}
type Address {
street: String!
line2: String
city: String!
state: Lookup!
country: Lookup!
zip: String!
}
type Lookup {
id: ID!
value: String!
}
jobRole, city and state are all fields that have a predetermined list of values that are needed in various dropdowns in forms around the app.
What would be the best practice in the schema design for this case? I'm considering the following option:
query {
lookups {
jobRoles {
id
value
}
}
}
This has the advantage of being data driven so I can update my job roles without having to update my schema, but I can see this becoming cumbersome. I've only added a few of our business objects, and already have about 25 different types of lookups in my schema and as I add more data into the API I'll need to somehow to maintain the right lookups being used for the right fields, dealing with general lookups that are used in multiple places vs ultra specific lookups that will only ever apply to one field, etc.
Has anyone else come across a similar issue and is there a good design pattern to handle this?
And for the record I don't want to use enums with introspection for 2 reasons.
With the number of lookups we have in our existing data there will be a need for very frequent schema updates
With an enum you only get one value, I need a code that will be used as the primary key in the DB and a descriptive value that will be displayed in the UI.
//bad
enum jobRole {
MANAGER
ENGINEER
SALES
}
//needed
[
{
id: 1,
value: "Manager"
},
{
id: 2,
value: "Engineer"
},
{
id: 3,
value: "Sales"
}
]
EDIT
I wanted to give another example of why enums probably aren't going to work. We have a lot of descriptions that should show up in a drop down that contain special characters.
// Client Type
[
{
id: 'ENDOW',
value: 'Foundation/Endowment'
},
{
id: 'PUBLIC',
value: 'Public (Government)'
},
{
id: 'MULTI',
value: 'Union/Multi-Employer'
}
]
There are others that are worse, they have <, >, %, etc. And some of them are complete sentences so the restrictive naming of enums really isn't going to work for this case. I'm leaning towards just making a bunch of lookup queries and treating each lookup as a distinct business object
I found a way to make enums work the way I needed. I can get the value by putting it in the description
Here's my gql schema definition
enum ClientType {
"""
Public (Government)
"""
PUBLIC
"""
Union/Multi-Employer
"""
MULTI
"""
Foundation/Endowment
"""
ENDOW
}
When I retrieve it with an introspection query like so
{
__type(name: "ClientType") {
enumValues {
name
description
}
}
}
I get my data in the exact structure I was looking for!
{
"data": {
"__type": {
"enumValues": [{
"name": "PUBLIC",
"description": "Public (Government)"
}, {
"name": "MULTI",
"description": "Union/Multi-Employer"
}, {
"name": "ENDOW",
"description": "Foundation/Endowment"
}]
}
}
}
Which has exactly what I need. I can use all the special characters, numbers, etc. found in our descriptions. If anyone is wondering how I keep my schema in sync with our database, I have a simple code generating script that queries the tables that store this info and generates an enums.ts file that exports all these enums. Whenever the data is updated (which doesn't happen that often) I just re-run the code generator and publish the schema changes to production.
You can still use enums for this if you want.
Introspection queries can be used client-side just like any other query. Depending on what implementation/framework you're using server-side, you may have to explicitly enable introspection in production. Your client can query the possible enum values when your app loads -- regardless of how many times the schema changes, the client will always have the correct enum values to display.
Enum values are not limited to all caps, although they cannot contain spaces. So you can have Engineer but not Human Resources. That said, if you substitute underscores for spaces, you can just transform the value client-side.
I can't speak to non-JavaScript implementations, but GraphQL.js supports assigning a value property for each enum value. This property is only used internally. For example, if you receive the enum as an argument, you'll get 2 instead of Engineer. Likewise, you would return 2 instead of Engineer inside a resolver. You can see how this is done with Apollo Server here.

ElasticSearch - Querying Embedded Nested Objects

Trying to have a Nested docs in a parent element. So, I have a location property and inside that I have phoneNumbers "Nested" group of phoneNumbers. Trying to query this for documents that have multiple phone numbers.
Data Set
_source: {
id: 123,
location:{ //type: object
phoneNumbers: [ //type:Nested
{
phone: 555-555-5555
type: cell
},
{
phone: 222-222-2222
type: office
},
{
phone: 333-333-3333
type: fax
}
]
}
}
I am trying write a query, where size of phoneNumber is greater than one.
If I try to do it as a "Nested" document, I get an error about "location" not a nested object, if I try a script filter with _source.location.phoneNumbers.size()>0 I get "cannot invoke method size() on null object"
What am I missing?

Can someone advise on an HBase schema click stream data

I would like to create a click stream application using HBase, in sql this would be a pretty simple task but in Hbase I have not got the first clue. Can someone advise me on a schema design and keys to use in HBase.
I have provided a rough data model and several questions that I would like to interrogate the data for.
Questions I would like to ask for accessing data
What events led to a conversion?
What was the last page / How many paged viewed?
What pages a customer drops off?
What products does a male customer between 20 and 30 like to buy?
A customer has bought product x also likely to buy product y?
Conversion amount from first page ?
{
PageViews: [
{
date: "19700101 00:00",
domain: "http://foobar.com",
path: "pageOne.html",
timeOnPage: "10",
pageViewNumber: 1,
events: [
{ name: "slideClicked", value: 0, time: "00:00"},
{ name: "conversion", value: 100, time: "00:05"}
],
pageData: {
category: "home",
pageTitle: "Home Page"
}
},
{
date: "19700101 00:01",
domain: "http://foobar.com",
path: "pageTwo.html",
timeOnPage: "20",
pageViewNumber: 2,
events: [
{ name: "addToCart", value: 50.00, time: "00:02"}
],
pageData: {
category: "product",
pageTitle: "Mans Shirt",
itemValue: 50.00
}
},
{
date: "19700101 00:03",
domain: "http://foobar.com",
path: "pageThree.html",
timeOnPage: "30",
pageViewNumber: 3,
events: [],
pageData: {
category: "basket",
pageTitle: "Checkout"
}
}
],
Customer: {
IPAddress: 127.0.0.1,
Browser: "Chrome",
FirstName: "John",
LastName: "Doe",
Email: "john.doe#email.com",
isMobile: 1,
returning: 1,
age: 25,
sex: "Male"
}
}
Well, you data is mainly in one-to-many relationship. One customer and an array of page view entities. And since all your queries are customer centric, it makes sense to store each customer as a row in Hbase and have customerid(may be email in your case) as part of row key.
If you decide to store one row for one customer, each page view details would be stored as nested. The video link regarding hbase design will help you understand that. So for you above example, you get one row, and three nested entities
Another approach would be, denormalized form, for hbase to perform good lookup. Here each row would be page view, and customer data gets appended for every row.So for your above example, you end up with three rows. Data would be duplicated. Again the video gives info regarding that too(compression things).
You have more nested levels inside each page view - live events and pagedata. So it will only get worse, with respect to denormalization. As everything in Hbase is a key value pair, it is difficult to query and match these nested levels. Hope this helps you to kick off
Good video link here

Resources