Query postgresql column which is an array of another entity - database

I'm using TypeOrm with PostgreSQL and have the following two entities:
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: string;
#ManyToMany(() => City)
#JoinTable()
#Length(2, 2)
cities: City[];
}
export class City {
#PrimaryGeneratedColumn()
id: string;
#Index()
#Column({ type: 'varchar', nullable: false })
name: string;
}
As you can see, each user can have two and only two cities.
Question:
How to fetch all the users who have both the city1 and the city2?
NB: city1 and city2 are possible values for City.name.
Example:
User #1 { id: 1, cities: [c1, c2] }
User #2 { id: 2, cities: [c1, c3] }
c1, c2 and c3 are cities in the City table.
fetchUsers([c1, c2]) = fetchUsers([c2, c1]) = [User #1]

Related

Cannot insert bigint in SQL Server using typeorm (NestJS)

I want to insert record in SQL Server using typeorm where column has type bigint. I have 'Cats' entity with id type: bigint.
import { Column, Entity } from 'typeorm';
#Entity('Cats')
export class CatsEntity {
#Column({ type: 'bigint', name: 'CatID' })
public id: string;
#Column('int', { primary: true, name: 'CatDB' })
public db: number;
#Column('varchar', { name: 'Name' })
public name: string;
#Column('datetime', { name: 'DDB_LAST_MOD' })
public ddbLastMod: Date;
}
And dto, that I get in controller:
export class InsertCatsDto {
public id: string;
public db: number;
public name: string;
}
Saving is performed in controller:
#Post('/cats')
public async insertEobResponse(#Body() insertCatsDto: InsertCatsDto): Promise<any> {
const cats = new CatsEntity();
cats.id = insertCatsDto.id;
cats.db = insertCatsDto.db;
cats.name = insertCatsDto.name;
cats.ddbLastMod = new Date();
return this.catsRepository.insert(cats);
}
But when I send request with id as a string via Postman I get the following error:
"error": "Error: Validation failed for parameter '0'. Value must be between -9007199254740991 and 9007199254740991, inclusive. For smaller or bigger numbers, use VarChar type."
I'm not sure if I'm just missing something or need to make some transformation of values or if this is a real issue with typeorm.
To make your code work with bigInt in typeorm you just need to change type in entity from "bigint" to "varchar":
import { Column, Entity } from 'typeorm';
#Entity('Cats')
export class CatsEntity {
#Column({ type: 'varchar', name: 'CatID' })
public id: string;
#Column('int', { primary: true, name: 'CatDB' })
public db: number;
#Column('varchar', { name: 'Name' })
public name: string;
#Column('datetime', { name: 'DDB_LAST_MOD' })
public ddbLastMod: Date;
}

GraphQL query for interface or union type

We are implementing an app in React-Naitive and for this we are using aws and amplify. Now we are trying to get all elements of an interface or union type in graphql. The Interface is calling TrackingItem and the type which are implementing this is called UserFood and UserSymptom. We tried this also, with union and just a array of TrackingItems. But with every possibility we don’t get any element. The return value is just null and we are expect the ID of TrackingItems, or in case of getAllTrackingItems an array of IDs from TrackingItem.
Graphql-schema:
type Query {
getAllTrackingItems: [TrackingItem]
# Retrieve tracking items
findTrackingItem(id: ID!): TrackingItem
# Search across all UnionTrackingItems
search(id: ID!): [UnionTrackingItems]
}
union UnionTrackingItems = UserSymptom | UserFood
interface TrackingItem {
id: ID!
userId: ID!
}
type UserFood implements TrackingItem #model {
id: ID!
userId : ID!
type: String!
foodId: ID!
food : Food #connection(fields: ["foodId"])
}
type UserSymptom implements TrackingItem #model {
id: ID!
userId : ID!
type: String!
symptomId: ID!
symptom : Symptom #connection(fields: ["symptomId"])
strenght: Int
}
Our queries which we are testing after amplify mock:
query MyQuery {
getAllTrackingItems {
id
}
findTrackingItem(id: 1) {
id
}
search(id: 1) {
... on UserFood {
id
}
}
getUserFood(id: 1) {
id
}
}
Our results:
{
"data": {
"getAllTrackingItems": null,
"findTrackingItem": null,
"search": null,
"getUserFood": {
"id": "1"
}
}
}
Can anyone help? Thank you!

How to query only objects containing each element from the array given as a variable using Hasura?

I have a table 'Students' in my db(postgress with Hasura) with relation many-to-many with 'Subjects':
type Student = {
id: uuid
name: String
subjects: [subject]
}
type Subject = {
id: uuid
name: String
}
I have a Static QUERY1:
query FilteredStudents($subjects: [String!]) {
students(where: { subjects: { name: { _in: $subjects } } }) {
id
name
}
}
e.g.:
$subjects = ['Math', 'English', 'Physics']
It will find all the students that attend to ANY of those classes.
e.g.:
const student1 = {
id: 1,
name: 'Mike',
subjects: ['Physics', 'Chemistry'] // subjects mapped to names for simplicity
}
My problem is that I want another query which will find all the students that attend to EACH of those classes.
So it shouldn't fetch student1, but should fetch students like this:
const student2 = {
id: 2,
name: 'Walt',
subjects: ['Math', 'English', 'Physics', 'Some', 'other', 'subjects'] // subjects mapped to names for simplicity
}
My only idea was to create dynamic queries like this:
Dynamic QUERY2 (a new query is generated (on runtime) every time the $subject array changes):
query FilteredStudents {
students(where: { _and: [
subjects: { name: { _eq: "Math" } }
subjects: { name: { _eq: "English" } }
subjects: { name: { _eq: "Physics" } }
]}) {
id
name
}
}
But I would really want to avoid that and find some static solution. Is there a way to achieve this using filters offered by Hasura? (https://hasura.io/docs/1.0/graphql/manual/queries/query-filters.html#)
I can name your QUERY2 as static already and QUERY1 as dynamic - 1st is parametrized, 2nd is hardcoded.
You can construct and pass as variable entire where object for both.
You can read this and use _not with _nin to do the same (as '_and' usage). It stil will be a dynamic condition because where is an input type ... and almost the same condition object creation complexity.
update
const subset = ['Math', 'English'];
const condition = { _and: [] };
subset.map( el => {
condition._and.push( {
subjects: { name: { _eq: el } }
});
});
callSomeLazyQuery( { variables: {
where: condition
} );
the same should be valid
const condition = {
_not: {
_and: []
}
};
subset.map( el => {
condition._not._and.push( {
subjects: { name: { _nil: el } }
});
});

LinkingObjects in react-native realm

I am currently trying to get the Realm Database for my react-native Application working, but I am unable to create a link between two Objects.
I am able to fetch Objects, I am able to create single Objects, but I am unable to link two Objects together
I followed the documentation, specifically I am looking at creating a Inverse Relationship
class PersonSchema {
public static schema: Realm.ObjectSchema = {
name: 'Person',
primaryKey: 'id',
properties: {
id: 'string',
username: 'string',
dogs: 'Dog[]',
},
};
}
class DogSchema {
public static schema: Realm.ObjectSchema = {
name: 'Dog',
primaryKey: 'id',
properties: {
id: 'string',
name: 'string',
owner: {type: 'linkingObjects', objectType: 'Person', property: 'dogs'},
},
};
}
I open my Realm with both schemas
componentDidMount() {
Realm.open({
schema: [PersonSchema.schema, DogSchema.schema],
deleteRealmIfMigrationNeeded: true,
}).then(realm => {
this.setState({realm});
});
}
One thing I tried was the following:
createPerson = () => {
const id = uuid();
const personenName = 'Steve ' + id;
const realm = this.state.realm;
if (realm) {
realm.write(() => {
const dog = realm.create('Dog', {
id,
name: 'Bello ' + id,
});
const dogs = realm.objects('Dog');
const person = realm.create('Person', {
id,
username: personenName,
dogs: [],
});
const persons = realm.objects('Person');
person.dogs.push(dog);
});
}
};
But I also tried linking the Dog to the Person. I tried creating a Dog and in that call create a Person for him and vice versa ... All tries throw an Error. The above Code just freezes the App.
How do I properly link two Objects together ?
For my App I want to link stuff to the User so I can look it up faster.

Typescript tells me method is property and can't create Object

iam new to typescript and don't understand the following behaviour. I have an interface like this:
import { Titles } from "../enumerations/titles";
/**
* Representing a Person
*/
export interface Person{
id: number;
title: Titles
firstName: string;
lastName: string;
getName(): string;
}
And now I want to create an Const Array for mocking some Employees. Therefore I got this class:
import { Person } from "../interfaces/person";
import { Titles } from "../enumerations/titles";
/**
* Represents an Employee
*/
export class Employee implements Person{
id: number;
title: Titles
firstName: string;
lastName: string;
getName(): string {
if (this.title === Titles.Nothing){
return this.firstName + " " + this.lastName;
}
return this.title + " " + this.firstName + " " + this.lastName;
}
}
And the Constant:
import { Titles } from "../enumerations/titles";
import { Person } from "../interfaces/person";
export const PROJECTMANAGER: Employee[] = [
{ id: 1, title: Titles.Nothing, firstName: "Max", lastName: "Mustermann" },
{ id: 2, title: Titles.Nothing, firstName: "Willy", lastName: "Brandt" },
{ id: 3, title: Titles.Dr, firstName: "Walter", lastName: "Steinmeier" }
];
The precompiler told me that this can't work, because Property getName isn't declared in my example values. But this is a Method I just want to initilize some Persons to fill the array.
The Type "({ id: number; title: Titles.Nothing; firstName: string; lastName: string; } | { id: number; titl..." cannot be assigned to "Employee[]".
The Property "getName" is missed in Type "{ id: number; title: Titles.Nothing; firstName: string; lastName: string; }".
Someone can help? I'm sure it's stupid but I'm stucking.
The problem is that object literals are not instances of the class Employee. In order to create an instance of Employee you need to use the new operator ( new Employee() ).
Since typescript uses structural compatibility to determine type compatibility, you can assign an object literal if you provide ALL the members of the class. But the object literal will still not be an instance of the class:
let emp: Employee = {
id: 1, title: Titles.Nothing, firstName: "Max", lastName: "Mustermann",
getName : Employee.prototype.getName
} // This is ok, we have the getName member
console.log(emp instanceof Employee) /// Still false, not an instance since we did not create it using new Employee
A better option would be to provide a constructor that accepts the object literal as a parameter an use that:
export class Employee implements Person{
constructor (data: Partial<Employee>) {
Object.assign(this, data);
}
/// ....
}
let emp: Employee = new Employee({
id: 1, title: Titles.Nothing, firstName: "Max", lastName: "Mustermann",
});
console.log(emp instanceof Employee) /// True now
Since Employee is a class, not a simple object, you need to create new Employees with new, not with a simple object declaration.
Define a constructor that takes id, title, firstName, and lastName as arguments, then do something like this:
export const PROJECTMANAGER: Employee[] = [
new Employee(1, Titles.Nothing, "Max", "Mustermann"),
new Employee(2, Titles.Nothing, "Willy", "Brandt"),
new Employee(3, Titles.Dr, "Walter", "Steinmeier")
];

Resources