How to make very nested queries using TypeORM and TypeGraphql - typeorm

I'm learning both TypeORM and TypeGraphQL, migrating from Postgraphile. In Postgraphile I had the option of making very nested queries like the case I'm having problems with. As a crude example, I can have those entities (please consider it as a very crude example):
user{
userId: number;
userName: string;
cars: car[];
}
car{
carId: number;
owner: user;
carBrand: brand;
}
brand{
brandId: number;
brandName: string;
cars: car[];
}
I understand the concept behing the 'relations' option from the Find or Findby method, however, I can't go depper than a few levels.
How should I tackle a query like this? "The name of the owners of the cars that share the brands of the cars of an specific user"
user{
userId
cars{
carId
brand{
brandName
cars{
owner{
userId
userName
}
}
}
}
}
Regards!

Related

Unable to create realtions in graphql neo4j

type User {
user_name: String
Age: Float
Drinking: Boolean
Nationality: String
sex: String
Smoking: Boolean
Weight: Float
sufferingFromDisease: disease #relationship(type: "suffering_from", direction: OUT)
haveInFamilyHistory: history #relationship(type: "have_in_family", direction: OUT)
activityOnTodayDate: today_date #relationship(type: "activity_on", direction: OUT)
}
type disease {
disease_name: String
Medication: String
Time_period: Float
userSufferingFrom: User #relationship(type: "suffering_from", direction: IN)
}
I am using this type definitions in graphql to create the graph. I have created the user node and disease node without relations. Now i want to create the relations without editing the nodes like merge in the cypher. can some one help
mutation{
createUsers(input:{
sufferingFromDisease
})
{
users{
sufferingFromDisease
}
}
}
I was trying this above mutation to create relations but no luck
If you want to create a relationship when 2 nodes already exist in the database, you should perform an update operation with a connect parameter, such as:
mutation Mutation {
updateUsers(
where: { user_name: "arthur_dent" }
connect: { sufferinFromDisease: { where: { node: { disease_name: "Great Green Arkleseizure" } } } }
) {
users {
user_name
}
}
}
Sadly, documentation on this area is a bit lacking, although any introspection tool such as GraphiQL will help you find all the alternatives and syntax for connections.
You can find a few examples following the relationships section of the official documentation

How to store relational (one to many or many to one) data with Amplify iOS (AppSync)?

today checking some of the amplify documentation (I know this one says it is a preview in the iOS scenario) but I have ran into a road block.
Assumptions
Amplify is correctly configured in my iOS project. I can push data to Person and query the Amplify.API
The schema has been defined as:
type Person #model {
id: ID!
name: String!
possessions: [Thing] # list of things this person owns.
#connection(keyName: "byPerson", fields: ["id"])
}
type Thing #model
#key(name: "byPerson", fields: ["personId"]) {
id: ID!
name: String!
personId: ID!
ownerOfThings: Person # defining the 'belongsTo' property.
#connection(fields: ["personId"])
}
This generates the following code:
public struct Person: Model {
public let id: String
public var name: String
public var possessions: List<Thing>?
public init(id: String = UUID().uuidString,
name: String,
possessions: List<Thing>? = []) {
self.id = id
self.name = name
self.possessions = possessions
}
}
public struct Person: Model {
public let id: String
public var name: String
public var ownerOfThings: Person?
public init(id: String = UUID().uuidString,
name: String,
ownerOfThings: Person? = nil) {
self.id = id
self.name = name
self.ownerOfThings = ownerOfThings
}
}
Here is where I ran into trouble. Amplify.API doesn't seem be saving my object and its associated data in a single mutation. I have to call it as nested operations to have an effect.
// sample on how I am trying to save data.
var thing = Thing(name: "Long Claw")
let person = Person(
name: "Jon Snow",
possessions: List([ thing ])
)
Amplify.API.mutate(of: person, type: .create) { ev in
// doing something with the event.
print(String(describing: ev)) // this works. It saves the instance to DynamoDB
// unfortunately, it did not save the instance of thing... let's try to correct this.
thing.ownerOfThings = person
Amplify.API.mutate(of: thing, type: .create) { ev2 in
// do something else with this...
print(String(describing: ev2))
// this ^ crashes badly...
}
}
The code above will generate an output similar to:
Result.success(Person(id: "EC4BEEE1-C1A1-4831-AB86-EA1E22D8AD48", name: "Jon Snow", possessions: nil))
GraphQLResponseError<Thing>: GraphQL service returned a successful response containing errors: [Amplify.GraphQLError(message: "Variable \'input\' has coerced Null value for NonNull type \'ID!\'", locations: Optional([Amplify.GraphQLError.Location(line: 1, column: 26)]), path: nil, extensions: nil)]
I've tried declaring the relationship as:
type Person #model {
id: ID!
name: String!
possessions: [Thing] # list of things this person owns.
#connection(keyName: "byPerson", fields: ["id"])
}
type Thing #model
#key(name: "byPerson", fields: ["personId"]) {
id: ID!
name: String!
personId: ID!
# ownerOfThings: Person
# #connection(fields: ["personId"]) # Not belongsTo for you!
}
Or a variation of this, defining the possessions as possessions: [Thing] #connection.
All of them generate various (although some what related) errors, preventing me from storing my data.
So, the question is:
How do you specify the relationship in iOS to save it?

How to make makeExecutableSchema ignore directives?

Is there a way to tell makeExecutableSchema from graphql-tools to ignore certain directives?
I want to query my neo4j database with graphql. I also want to be able to specify subtypes in graphql. There is a library called graphql-s2s which adds subtypes to graphql. The library neo4j-graphql-js uses custom directives (#cyper and #relation) to build an augmented Schema. It takes typeDefs or an executableSchema from graphql-tools. qraphql-s2s lets me create an executableSchema out of the Schema containing subtypes. My hope was that I should be easy to just pipe the different schema outputs into each other like in a decorator pattern.
Unfortunately this is apparently not how it works as I get a lot of parser error messages, which are not really descriptive.
Unfortunately I haven't found any Grandstack documentation where it is shown how to use augmentSchema() on an executableSchema with relations and cypher in it.
Is there a way how to do this?
Below my naive approach:
const { transpileSchema } = require('graphql-s2s').graphqls2s;
const { augmentSchema } = require('neo4j-graphql-js');
const { makeExecutableSchema} = require('graphql-tools');
const { ApolloServer} = require('apollo-server');
const driver = require('./neo4j-setup');
/** The #relation and #cypher directives don't make any sense here they are
just for illustration of having directives that make sense to
'augmentSchema' and not to 'makeExecutableSchema' **/
const schema = `
type Node {
id: ID!
}
type Person inherits Node {
firstname: String
lastname: String #relation(name: "SOUNDS_LIKE", direction: "OUT")
}
type Student inherits Person {
nickname: String #cypher(
statement: """ MATCH (n:Color)...some weird cypher query"""
)
}
type Query {
students: [Student]
}
`
const resolver = {
Query: {
students(root, args, context) {
// Some dummy code
return [{ id: 1, firstname: "Carry", lastname: "Connor", nickname: "Cannie" }]
}
}
};
const executabledSchema = makeExecutableSchema({
typeDefs: [transpileSchema(schema)],
resolvers: resolver
})
const schema = augmentSchema(executabledSchema)
const server = new ApolloServer({ schema, context: { driver } });
server.listen(3003, '0.0.0.0').then(({ url }) => {
console.log(`GraphQL API ready at ${url}`);
});

Grails - CreateCriteria to Retrieve any entry that contains any element in query

Given I have this domain:
class Game {
Set<GameType> gameType
String name
}
And this enum:
enum Gametype {
RHYTHM, ADVENTURE, PUZZLE, RPG, HORROR, FIGHTING, MOBA, MMO
}
I need to retrieve a list of games that contains at least one of the game types indicated in the query. I tried using this code:
def retrieveGamesThatMayBeUnderGameTypes( List<GameType> listOfGameTypes) {
return Game.createCriteria().list(){
'in'("gameType", listOfGameTypes)
}
}
However, it returns a NullPointerException. Any ideas?
Just make sure your enum (Gametype) has a field called id. Something like:
enum Gametype {
RHYTHM('RHYTHM'),
ADVENTURE('ADVENTURE'),
....
String id
Gametype(String id) {
this.id = id
}
}
See this answer for more: Grails Enum Mapping

many-to-many retrieve only one row

I have a relationship between two domain class: User and Bank, user has many of bank and bank has many of user, the result table I call it as mm_user_banks that keep both table IDs for MM relationship.
class User {
String name
String password
Date createdAt = new Date()
Date loginAt
static hasMany = [banks:Bank]
static fetchMode = [banks: 'eager']
static constraints = {
}
static mapping = {
banks joinTable: [name: 'mm_user_banks', key: 'mm_user_id']
}
}
and Bank...
class Bank {
Long id
String name
static belongsTo = User
static hasMany = [users:User]
static constraints = {
}
static mapping = {
id generator: 'assigned'
users joinTable: [name: 'mm_user_banks', key: 'mm_bank_id'], lazy: false
}
}
I can save users with banks as well, but the problem is when I try to retrieve bank list from an user instance and it only fetch one row even if there is more than one row for this user in mm_user_banks table.
E.g:
User u = new User(name: 'user', password: 'pwd')
u.addToBanks(Bank.findById(1))
u.addToBanks(Bank.findById(2))
u.addToBanks(Bank.findById(3))
u.save(flush: true)
In database it is OK, fetching 3 rows, but when I get the user and see its bank list:
def user = User.findById(1) //OK
println "Size ${user.banks?.size()}" //only 1??? How?
Thanks in advance!
Just tested it out - "user.banks?.size()" returns "3". Are you sure that data in DB is OK?
Anyway, if you want to use eager fetching for collections then define it in "mapping" of User class (instead of "fetchMode" static field):
static mapping = {
banks joinTable: [name: 'mm_user_banks', key: 'mm_user_id'], fetch: 'join'
}
in Bank class use fetch: 'join' in mapping instead of lazy: false
Thanks so much, Sergei, but didn't worked out.
I fixed it in an ugly way, but this is was my remaining way out.
I created another domain class to mapping the MM table, so I did a mm_user_banks class. I use it to fetch records from bank or user and worked OK. To save banks for a user I actually do it in the old way as well, not changed from that. I guess this mighty not be the best way, but like I said, worked out.
I've tried "fetch: 'join'" and "lazy: false" and "static fetchMode = [banks: 'eager']" without success.
The new domain class is:
class UserBanks {
User user
Bank bank
static constraints = {
}
static mapping = {
table name: 'mm_user_banks'
user column: 'mm_user_id'
bank column: 'mm_bank_id'
}
}
I had the similar problem but in my case I had another relation between my equivalents to User and the Bank. This made the hasMany statement to use the wrong relation to map the many to many relation. In my case it was solved by adding a mappedBy statement to the relation:
class Bank{
...
static mappedBy=[users:'banks']
...
}
and
class User{
...
static mappedBy=[banks:'users']
...
}
or as it was in my case, since it was a uni-directional relation:
class ArticleGroup {
String name
static hasMany = [articles:Article]
static mappedBy = [articles: 'none']
static constraints = {
name(nullable:false, blank:false, unique:true, maxSize:100)
}
static mapping = {
table 'article_group'
sort 'name'
articles joinTable: [name:'article_group_article', key: 'articleGroup_id', column:'article_id'], fetch: 'join'
}

Resources