References a sub model from parent in typescript using prisma client - next.js

I am learning prisma and I can't figure out how to use the prisma types correctly if the returned data includes a sub model.
For example, I have the following two tables
model Services {
id Int #id #default(autoincrement())
service_name String #db.VarChar(255)
description String #db.MediumText
overall_status ServiceStatus #default(OPERATIONAL)
deleted Boolean #default(false)
sub_services SubServices[]
}
model SubServices {
id Int #id #default(autoincrement())
name String #db.VarChar(255)
description String #db.MediumText
current_status ServiceStatus #default(OPERATIONAL)
service Services? #relation(fields: [service_id], references: [id], onDelete: Cascade)
service_id Int?
}
I am then pulling data from the Services model using the following:
const services = await prisma.services.findMany({
where: {
deleted: false
},
include: {
sub_services: true
}
});
I am then in the client side referencing the Services model, but the IDE isn't detecting that Services can include sub_services. I can use it and it works but the IDE is always showing a squiggly line as if the code is wrong, example is below:
import {Services} from "#prisma/client";
const MyComponent : React.FC<{service: Services}> = ({services}) => {
return (
<>
service.sub_services.map(service => {
})
</>
)
}
but in the above example sub_services is underlined with the error TS2339: Property 'sub_services' does not exist on type 'Services'.
So how would I type it in a way that IDE can see that I can access sub_services from within services model.
UPDATE
I found a way to do it, but I'm not sure if this is the correct way or not as I am creating a new type as below:
type ServiceWithSubServices <Services> = Partial<Services> & {
sub_services: SubServices[]
}
and then change the const definition to the below
const ServiceParent : React.FC<{service: ServiceWithSubServices<Services>}> = ({service}) => {
Although this does seem to work, is this the right way to do it, or is there some more prisma specific that can do it without creating a new type.

In Prisma, by default only the scalar fields are included in the generated type. So, in your case for the Services type, all the scalar fields except sub_services would be included in the type. sub_services is not included because it's a relation field.
To include the relation fields, you would need to use Prisma.validator, here's a guide on generating types that include the relation field.

Related

Creating custom GraphQL schema for Drupal 9 empty fields which are paragraph references

Have a decoupled Drupal 9 with Gatsby and a GraphQL. On Drupal's side there is a node called school there is a field (field_components) which is an Entity Reference Field which can have unlimited number of references to paragraphs. There are over 50 paragraph types on the site but that specific field only accept four (4) types. And I am trying to define their types in GraphQL.
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
type node__school implements Node {
field_location: String
field_type_r_a: Boolean
relationships: node__schoolRelationships
}
type node__schoolRelationships {
field_components: // this is where i need to define the 4 types
}
`
createTypes(typeDefs);
};
As you can see by the example above I've written out 90% of the necessary schema but I have no idea how to define the for paragraph types. I'm guessing that each individual paragraph would be called paragraph__machine_name (e.g. paragraph__carousel) but since there are four (4) of them I don't know how to chain them (define them all)
Any ideas?
From the GraphQL docs:
Unions and interfaces are abstract GraphQL types that enable a schema field to return one of multiple object types.
In action (using paragraph entities):
const typeDefs = `
type node__school implements Node {
field_location: String
field_type_r_a: Boolean
relationships: node__schoolRelationships
}
union fieldContentParagraphUnion =
paragraph__foo
| paragraph__bar
| paragraph__bat
type paragraph__foo implements Node {
field_1: String
}
type paragraph__bar implements Node {
field_2: String
}
type paragraph__bat implements Node {
field_3: String
}
type node__schoolRelationships {
field_components: [fieldContentParagraphUnion] #link(from: "field_components___NODE")
}
`
This official Gatsby plugin helped me tame my schema-related issues: gatsby-plugin-schema-snapshot
Saves a minimal schema to file, adds the #dontInfer directive to all top-level types, and re-creates the schema from the saved type definitions during bootstrap. Use this plugin if you intend to lock-down a project’s GraphQL schema.

Getting started querying sync data from Realm

I'm attempting to get a list of items from a MongoDB Atlas instance via Realm into my Xamarin Forms application. I'm pretty sure I've followed the instructions correctly, however I can't seem to see any values come in.
I'm using Realm and Realm.Fody version: 10.2.0
I've uploaded my data with the following script
mongoimport --uri mongodb+srv://[user]:[pass]#cluster0.[wxyz].mongodb.net/[company] --collection products --type json --file products --jsonArray
1057 document(s) imported successfully. 0 document(s) failed to import.
When I go to MongoDB Atlas, I see this
In my App.xaml.cs constructor, I create a realm app and log in with anonymous credentials
public const string MasterDataPartitionKey = "master_data";
ctor()
{
var app = Realms.Sync.App.Create("my-app-id");
app.LogInAsync(Credentials.Anonymous()).ContinueWith(task => User = task.Result);
}
After this, in my first ViewModel constructor (it's Rx, but isn't doing anything fancy)
ctor()
{
_listProductsCommand = ReactiveCommand.Create<Realm, IEnumerable<Product>>(ExecuteLoadProducts);
_listProductsCommand.ThrownExceptions.Subscribe(x => { /* checking for errors here */ }).DisposeWith(TrashBin);
Initialize
.ObserveOn(RxApp.MainThreadScheduler)
// note MasterDataPartitionKey is the value I've set on every single record's `_partitionKey` property.
.Select(_ => new SyncConfiguration(MasterDataPartitionKey, App.User))
.SelectMany(Realm.GetInstanceAsync)
.Do(_ => { }, ex => { /* checking for errors here */ })
.ObserveOn(RxApp.MainThreadScheduler)
.InvokeCommand(this, x => x._listProductsCommand)
.DisposeWith(TrashBin);
}
And later, a simple query
private static IEnumerable<Product> ExecuteLoadProducts(Realm realm)
{
var data = realm.All<ProductDto>();
var productDtos = data.ToList();
var products = productDtos.Select(x => x.Map());
return products;
}
Expected:
productDtos (and products) should have a count of 1057
Actual:
productDtos (and products) have a count of 0
I've looked in my Realm logs and I can see the connections and sync logs
My anonymous authentication is turned on
and I've made it so that all of my Collections have read access (in fact developer mode is on)
Here's an example of one of the records
Here's a snipped of the dto I'm trying to pull down
I feel as though I must be missing something simple. Can anyone see anything obvious that could be sending me sideways?

How do I suppress CosmosDB "default" info in resultsets?

I want to suppress the CosmosDB information in the following resultset, how can that be done?
{
"id": null,
"_rid": null,
"_self": null,
"_ts": 0,
"_etag": null,
"topLevelCategory": "Shorts,Skirt"
},
This is an extract of course but I dont want to show the ID etc as they serve no purpose in this result but I cannot figure out how to suppress that info.
I expect the following
{
"topLevelCategory": "Shorts,Skirt"
},
Query looks as follows
$"SELECT DISTINCT locales.categories[0] AS topLevelCategory " +
$"FROM c JOIN locales in c.locales " +
$"WHERE locales.country = '{apiInputObject.Locale}' " +
$"AND locales.language = '{apiInputObject.Language}'";
Interesting thing is if I cast the result as a JOBJECT I dont get the system data, I only get it if I createDOcumentQuery as DOcument, so a workaround would be as follows
IQueryable<JObject> queryResultSet = client.CreateDocumentQuery<JObject>(UriFactory.CreateDocumentCollectionUri(databaseName, databaseCollection), parsedQueryObject.SqlStatement, queryOptions);
but that has other async issues but the above does not show the system generate IDs but the below one does
var query = client.CreateDocumentQuery<Document>(UriFactory.CreateDocumentCollectionUri(databaseName, databaseCollection), parsedQueryObject.SqlStatement, queryOptions).AsDocumentQuery();
var result = await query.ExecuteNextAsync<Document>();
These are system-generated properties of items in Cosmos DB.
Surely,you could filter them in the sql: select c.topLevelCategory from c, don't mention them or use select * from c. Filtering in sql is the best method, better than secondary processing of result set.
Update Answer:
Your situation is executing the exact same query the JOBJECT does not show the system data but the Document does.
My explanation as below:
Document Class is a self-contained base class of Document DB .NET package.It has these generate properties:
SDK will try to map the result data one by one to the entity class which you defined in the CreateDocumentQuery<T>.
So actually,you already find the solution.You could define your custom pojo to receive the result data. Just contain the properties you want in that pojo inside like:
class Pojo : Document
{
public string id { get; set; }
public string name { get; set; }
}
That would have both business implications and no more redundant fields.Hope i'm clear on this.

How to implement redux-search

I am trying to implement a search filter in my application which uses react/redux using redux-search. The first gotcha I get is when I try to add the store enhancer as in the example.
// Compose :reduxSearch with other store enhancers
const enhancer = compose(
applyMiddleware(...yourMiddleware),
reduxSearch({
// Configure redux-search by telling it which resources to index for searching
resourceIndexes: {
// In this example Books will be searchable by :title and :author
books: ['author', 'title']
},
// This selector is responsible for returning each collection of searchable resources
resourceSelector: (resourceName, state) => {
// In our example, all resources are stored in the state under a :resources Map
// For example "books" are stored under state.resources.books
return state.resources.get(resourceName)
}
})
)
I understand evarything up to the resourceSelector, when I tried to get a deep dive into the example to see how it works but I can barely see how they are generated and the last line returns an error, Cannot read property 'get' of undefined
My state object looks like this
state: {
//books is an array of objects...each object represents a book
books:[
//a book has these properties
{name, id, author, datePublished}
]
}
Any help from anyone who understands redux-search is helpful
If this line:
return state.resources.get(resourceName)
Is causing this error:
Cannot read property 'get' of undefined
That indicates that state.resources is not defined. And sure enough, your state doesn't define a resources attribute.
The examples were written with the idea in mind of using redux-search to index many types of resources, eg:
state: {
resources: {
books: [...],
authors: [...],
// etc
}
}
The solution to the issue you've reported would be to either:
A: Add an intermediary resources object (if you think you might want to index other things in the future and you like that organization).
B: Replace state.resources.get(resourceName) with state[resourceName] or similar.

Objects with multiple key columns in realm.io

I am writing an app using the Realm.io database that will pull data from another, server database. The server database has some tables whose primary keys are composed of more than one field. Right now I can't find a way to specify a multiple column key in realm, since the primaryKey() function only returns a String optional.
This one works:
//index
override static func primaryKey() ->String?
{
return "login"
}
But what I would need looks like this:
//index
override static func primaryKey() ->[String]?
{
return ["key_column1","key_column2"]
}
I can't find anything on the docs on how to do this.
Supplying multiple properties as the primary key isn't possible in Realm. At the moment, you can only specify one.
Could you potentially use the information in those two columns to create a single unique value that you could use instead?
It's not natively supported but there is a decent workaround. You can add another property that holds the compound key and make that property the primary key.
Check out this conversation on github for more details https://github.com/realm/realm-cocoa/issues/1192
You can do this, conceptually, by using hash method drived from two or more fields.
Let's assume that these two fields 'name' and 'lastname' are used as multiple primary keys. Here is a sample pseudo code:
StudentSchema = {
name: 'student',
primaryKey: 'pk',
properties: {
pk: 'string',
name: 'string',
lastname: 'string',
schoolno: 'int'
}
};
...
...
// Create a hash string drived from related fields. Before creating hash combine the fields in order.
myname="Uranus";
mylastname="SUN";
myschoolno=345;
hash_pk = Hash( Concat(myname, mylastname ) ); /* Hash(myname + mylastname) */
// Create a student object
realm.create('student',{pk:hash_pk,name:myname,lastname:mylastname,schoolno: myschoolno});
If ObjectId is necessary then goto Convert string to ObjectID in MongoDB

Resources