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.
Related
I have a Class schema that looks like this:
const ClassSchema = new mongoose.Schema({
title: {
type: String,
...
},
classImageURL: {
type: String,
...
},
imageWidth: {
type: String,
...
},
imageHeight: {
type: String,
...
}
});
module.exports = mongoose.models.Class || mongoose.model("Class", ClassSchema);
And a Subject schema that looks like this:
const SubjectSchema = new mongoose.Schema({
subjectTitle: {
type: String,
...
},
subjectImageURL: {
type: String,
...
},
imageWidth: {
type: String,
...
},
imageHeight: {
type: String,
...
},
});
module.exports =
mongoose.models.Subject || mongoose.model("Subject", SubjectSchema);
On a dynamic page named [className], I am getting the data of the particular className from the database and destructured it. Now, on the class page, I want to send a post request to the database using all the fields titled in the Subject schema. But, I also want to add the class data that I got and add it to the Subject schema.
I used a state to hold all the data:
setForm({
subjectTitle: enteredSubjectTitle,
subjectImageURL: response.data.url,
imageWidth: response.data.width,
imageHeight: response.data.height,
classDetail: classDetail // this is the data I have on the particular class data
}); // I want to add
And I tried to make changes in the Subject schema like this:
classDetail: { Class }, // I added this in the last part of the schema
It results in a post error.
How can I achieve what I want to?
const MUTATION_QUERY = gql`
mutation MUTATION_QUERY(
$name: bigint!
) {
insert_name(
objects: {
name: $name
}
) {
returning {
id
name
}
}
}
`;
const [onClick, { error, data }] = useMutation<{}, {}>(MUTATION_QUERY, {
variables: {
name: 1234,
},
});
My mutation query is inserting name in my table and autogenerating the id. On console logging the data variable I can view the fields id and name in the data object. But I am not able to access them them individually. How can I console.log "id". Thank you.
the console.log(data) looks like : {insert_name: {...}}
which expands to :
insert_name:
returning: Array(1)
0: {id: 1, name: 1234}
length: 1
_proto_: Array(0)
_typename: "insert_name_mutation_response
You can access the fields of an object with .
For example, if your object looks like this -
data = {
id: 1,
name: 'Jane',
}
You can get just the id with data.id
This works no matter how many layers deep your object may go, so take this example -
data = {
person: {
id: 1,
name: 'Jane',
}
}
You could get the id of person with data.person.id.
console.log(data.insert_name.returning[0].id) will give you the id returned.
For it to work in typescript we need to change the query to add the return type of data
const [onClick, { error, data }] = useMutation<{ReturnInsertNameProps}, {}>(MUTATION_QUERY, {
variables: {
name: 1234,
},
});
interface ReturnInsertNameProps {
insert_name: ReturnQueryProps;
}
interface ReturnProps {
returning: MessageProps[];
}
interface NameProps {
id: number;
name: number;
}
We can also use onCompleted method provided in useMutation if we want to process the result of the query.
I have this kind of object:
export default class Route {
public id: number = 0;
public name: string = "";
public points: Point[] = []
public static schema: Realm.ObjectSchema = {
name: 'Route',
primaryKey: 'id',
properties: {
id: 'int',
name: 'string',
points: { type: 'list', objectType: 'Point' },
}
}
}
So, when i tried to add this object to realm db i've got such error: Cannot modify primary key after creation: 'Route.id'
realm.write(() => {
let id = realm.objects(Route.schema.name).length + 1;
let route = realm.create<Route>(Route.schema.name, {
id: id,
name: `Route ${id}`,
points: [],
});
});
So, what i missed?
My partner and I have searched everywhere and tried everything with the Mongo documentation to look up how to insert and update new schema and update all of the documents in the database. We did not have any luck. Right now we are trying to add two new fields onto all of the current documents within the database. Both are array fields which we have updated the schema but nothing showing for the documents themselves. ALSO I AM FULLY AWARE there are many questions that are similar but I wanted to see if anyone could figure out our problem since it seems to work for everyone else but not us
MongoDB documentation
update, $set and upsert aggregation functions
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//Schema for how we define a movie object
const MovieSchema = new Schema({
id: {
type: Number
},
title: {
type: String
},
year: {
type: Number
},
rating: {
type: String //(PG, PG-13, R, NR, MA)
},
cast: {
type: [String], //Hold multiple cast members based on how many the user types in
default: undefined
},
quotes: {
type: [String],
default: undefined
},
genres: {
type: [String],
default: undefined
},
synopsis: {
type: String
},
imageURL: {
type: String
},
bannerURL: {
type: String
}
})
const Movie = mongoose.model('movies', MovieSchema);
module.exports = Movie;
These are the new fields being added to all documents
comments:{
type: [String],
default: undefined
},
characters: {
type: [String]
default: undefined
}
we have done most of the mongo functions through the commandline and prefer to do it that way unless there isn't a way
Assuming you've already updated your schema to have the two new fields:
Movie.find()
.then((allMovies) => {
allMovies.forEach((movieSchema) => {
//create two new fields in each schema
movieSchema.comments = []
movieSchema.characters = []
//save the schema we updated
movieSchema.save()
})
})
.catch((errors) => {
return res.status(400).json({ nomoviesfound: "could not find movies"})
})
I have some json data in file called countryData.json structured as so:
{
"info":"success",
"stats":
[{
"id":"1",
"name":"USA",
"type":"WEST"
},
//...
I'm using graphQL to access this data. I have created an object type in the schema for countries using the following:
const CountryType = new GraphQLObjectType({
name: "Country",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
type: { type: GraphQLString },
})
});
I want to write a query that will allow me to access all of the elements of this array that have a certain "name" value(There can be multiple with the same name). I've written the following query, but it only returns the first match in the array:
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { type: { name: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
}
}
});
The "_" comes from const _ = require('lodash');
Also, how can I just get every single item in the array?
I have not recreated the code, therefore I can not check if it would be executed correctly. This is code, that should work in my opinion (without trying). If you want to return array of elements you need to implement https://lodash.com/docs/#filter. Filter will return all objects from stats, which match the argument name. This will return correctly inside resolver function, however, your schema needs adjustments to be able to return array of countries.
You need probably rewrite the arguments as follows as this is probably not correct. You can check out how queries or mutation arguments can be defined https://github.com/atherosai/express-graphql-demo/blob/feature/2-json-as-an-argument-for-graphql-mutations-and-queries/server/graphql/users/userMutations.js. I would rewrite it as follows to have argument "name"
args: { name: { type: GraphQLString } }
You need to add GraphQLList modifier, which defines, that you want to return array of CountryTypes from this query. The correct code should look something like this
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
},
countries: {
type: new GraphQLList(CountryType),
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.filter(countryData.stats, {name: args.name});
}
}
}
});
Now if you call query countries, you should be able to retrieve what you are expecting. I hope that it helps. If you need some further explanation, I made the article on implementing lists/arrays in GraphQL schema as I saw that many people struggle with similar issues. You can check it out here https://graphqlmastery.com/blog/graphql-list-how-to-use-arrays-in-graphql-schema
Edit: As for the question "how to retrieve every object". You can modify the code in resolver function in a way, that if the name argument is not specified you would not filter countries at all. This way you can have both cases in single query "countries".