update model in graphQL giving fields to update and array of id's - graphql

I have a problem.
I want to create query to update some fileds on multiple model,
it should looks like this:
mutation{
updateInternalOrder( input: {
state: {
connect: 1
}
id_internal_orders: [1,2] <= here
}){
id_internal_orders
qty
state {
id_internal_orders_states,
name
}
}
}
In this query i would like to assign(update) id_internal_orders_states(in states)
in id_internal_orders that has id: 1 and 2.
How to do that?
Schema(lighthouse-php) that works only if i provide a single id, not array:
extend type Mutation {
updateInternalOrder(input: UpdateInternalOrders! #spread): InternalOrders #update
}
input UpdateInternalOrders {
id_internal_orders: Int!
state: InternalOrdersStatesHasOne
qty: Int
id_supplier: Int
}
input InternalOrdersStatesHasOne {
connect: Int
}

Instead of this
input UpdateInternalOrders {
id_internal_orders: Int!
state: InternalOrdersStatesHasOne
qty: Int
id_supplier: Int
}
Your schema should look like this
input UpdateInternalOrders {
id_internal_orders: [Int]!
state: InternalOrdersStatesHasOne
qty: Int
id_supplier: Int
}
So this way id_internal_orders will be define as an array
Solution for the error Argument 2 passed to Nuwave\\Lighthouse\\Execution\\Arguments\\ArgPartitioner::relationMethods() must be an instance of Illuminate\\Database\\Eloquent\\Model, instance of Illuminate\\Database\\Eloquent\\Collection given
The error you get is because you might be using an ORM. The data passed to the mutation is a collection, probably because you manipulate model generated by your ORM. GraphQL expect an array and not a Collection.
You must either convert the collection in array. But this is not recommended. In case there is a collection of object with collection. You’ll have to convert the collection and all the collection inside each object of the parent collection. This can get complicated very fast.
Or you can find a way to not manipulate your model in your front end and manipulate data transfer object instead. But I can’t really help you here since I don’t know where the data come from.

Related

GQLGen related list query limit using entgql

I'm using entgql implementation of gqlgen (https://entgo.io/docs/graphql/) and have run into an issue where after my query reaches a certain size, it starts returning related lists as empty lists.
Rough data as follows
type Partner implements Node {
id: ID!
system: [System]
}
type System implements Node {
id: ID!
name: String
}
type PartnerConnection {
totalCount: Int!
pageInfo: PageInfo!
edges: [PartnerEdge]
}
type PartnerEdge {
node: Partner
cursor: Cursor!
}
type Query {
partners(
first: Int
): PartnerConnection!
}
And my query is as follows
query {
partners {
edges {
node {
system {
name
}
}
}
}
}
I've found that after the count of partner records goes over a certain count, the system list starts returning as an empty list for every record regardless of what data there is.
If I change my query to partners(first:100) then it returns the systems lists fine.
I get that I need to write my queries better so I'm not running into these limits in the first place, but I would like to know what exactly is causing this and how to possibly increase the limit in the short term.
The fact that it just starts returning empty lists rather than throwing some sort of limit error is also an issue.
I'm also unaware of the correct terminology around this issue which makes searching for a solution even more difficult.

Check if given type has a property named X. Reduce inline fragments

I have a query that fetches some events array. Each node inside of edges can implement on of finite number of interfaces.
Question:
Is it possible to check if a given node has a property named X (in this case id, timestamp and content) instead of using multiple inline fragments (... on {Type})?
events(last: $eventCount) {
edges {
node {
... on Type1 {
id
timestamp
content
}
... on Type2 {
id
timestamp
content
}
... on Type3 {
id
timestamp
content
}
... on Type4 {
id
timestamp
content
}
}
}
}
In this example I'd like to get rid of ... on Type1, ... on Type2 etc. and just check if id, timestamp and content properties exist.
There are two answers here depending on what you're trying to achieve, but the short answer is no: You can't conditionally spread a fragment based on the value you're reading.
However, what you can do is check the interface itself. You mentioned that these nodes all implement interfaces. So I'm assuming these nodes are either all implementing a common interface and nodes itself is either listing out an interface or a union of multiple types.
If you ensure that all your types, TypeN, are implementing an interface that includes the fields you're trying to check for then you can simply spread a fragment on this interface:
interface BaseType {
id: ID!
timestamp: DateTime
content: String
}
type TypeA implements BaseType {
id: ID!
timestamp: DateTime
content: String
# ...
}
Given this interface you can then query for every type implementing this interface:
{
... on BaseType { id timestamp content }
}
This will work even if you don't include all fields. I assume that content for instance may have a varying type, which means that you can't query it across all types at once.

insert items into array using graphql - Parse server

I have a class that contains a field called 'notes'. Its data type is array. In the mutation, I'm able to save data on the field. problem is it overwrites the value. I want to add value in the array. how do I do it? here's my mutation. I know I'm not doing the right thing, but can't find it in the documentation as well
mutation {
updateParcel(input: { id: "B6aESEwWcA", fields: { notes: ["wow"]}}) {
parcel {
objectId
notes {
... on Element {
value
}
}
}
}
}

How resolve the right type in GraphQL when using interface and inline fragments

I'm facing a problem where I need to reference a resolved field on the parent from inside the __resolveType. Unfortunately the field I need to reference did not come as part of the original api response for the parent, but from another field resolver, which I would not have though mattered, but indeed it does, so it is undefined.
But I need these fields (in this example the; obj.barCount and obj.bazCount) to be able to make the following query, so I've hit a dead end. I need them to be available in the resolveType function so that I can use them to determine what type to resolve in case this field is defined.
Here's an example:
The graphql query I wish to be able to make:
{
somethings {
hello
... on HasBarCount {
barCount
}
... on HasBazCount {
bazCount
}
}
}
Schema:
type ExampleWithBarCount implements Something & HasBarCount & Node {
hello: String!
barCount: Int
}
type ExampleWithBazCount implements Something & HasBazCount & Node {
hello: String!
bazCount: Int
}
interface Something {
hello: String!
}
interface HasBarCount {
barCount: Int
}
interface HasBazCount {
bazCount: Int
}
Resolvers:
ExampleWithBarCount: {
barCount: (obj) => {
return myApi.getBars(obj.id).length || 0
}
}
ExampleWithBazCount {
bazCount: (obj) => {
return myApi.getBazs(obj.id).length || 0
}
}
Problem:
Something: {
__resolveType(obj) {
console.log(obj.barCount) // Problem: this is always undefined
console.log(obj.bazCount) // Problem: this is always undefined
if (obj.barCount) {
return 'ExampleWithBarCount';
}
if (obj.bazCount) {
return 'ExampleWithBazCount';
}
return null;
}
}
Any ideas of alternative solutions or what am I missing?
Here's a little more about the use case.
In the database we have a table "entity". This table is very simple and only really important columns are id, parent_id, name. type, and then you can of course attach some additional metadata to it.
Like with "entity", types are created dynamically from within the backend management system, and aftewards you can assign a type to your concrete entity.
The primary purpose of "entity" is to establish a hierarchy / tree of nested entities by parent_id and with different "types" (in the type column of entity). There will be some different meta data, but let's not focus on that.
Note: entity can be named anything, and the type can be anything.
In the API we then have an endpoint where we can get all entities with a specific type (sidenote: and in addition to the single type on an entitiy we also have an endpoint to get all entities by their taxonomy/term).
In the first implementation I modeled the schema by adding all the "known" types I had in my specification from the UX'er during development. The tree of entities could be like eg.
Company (or Organization, ..., Corporation... etc)
Branch (or Region, ..., etc)
Factory (or Building, facility, ..., etc)
Zone (or Room, ..., etc)
But this hierarchy is just one way it could be done. The naming of each might be totally different, and you might move some of them a level up or down or not have them at all, depending on the use case.
Only thing that is set in stone is that they share the same database table, will have the type column/field defined and they may or may not have children. The bottom layer in the hierarchy will not have children, but machines instead. The rest of just diffent metadata, which I think we should ignore for to not complicate this further.
As you can see the hierarchy needs to be very flexible and dynamic, so I realized it wasn't a great solution I had begun on.
At the lowest level "Zone" in this case, there will need to be a "machines" field, which should return a list of machines (they are in a "machines" table in the db, and not part of the hierarchy, but simply related with an "entity_id" on the "machines" table.
I had schema types and resolvers for all in the above hierarchy: Organization, Branch, Factory, Zone etc, but I was for the most part just repeating myself, so I thought I could turn to interfaces to try to generalize this more.
So instead of doing
{
companies{
name
branchCount
buildingCount
zoneCount
branches {
name
buildingCount
zoneCount
buildings {
name
zoneCount
zones {
name
machines {
name
}
}
}
}
}
}
And having to add schema/resolvers for all the different namings of the entities, I thought this would work:
{
entities(type: "companies") {
name
... on HasEntityCount {
branchCount: entityCount(type: "branch")
buildingCount: entityCount(type: "building")
zoneCount: entityCount(type: "zone")
}
... on HasSubEntities {
entities(type: "branch") {
name
... on HasEntityCount {
buildingCount: entityCount(type: "building")
zoneCount: entityCount(type: "zone")
}
... on HasMachineCount {
machineCount
}
... on HasSubEntities {
entities(type: "building") {
name
... on HasEntityCount {
zoneCount: entityCount(type: "zone")
}
... on HasMachineCount {
machineCount
}
... on HasSubEntities {
entities(type: "zone") {
name
... on HasMachines {
machines
}
}
}
}
}
}
}
}
}
With the interfaces being:
interface HasMachineCount {
machineCount: Int
}
interface HasEntityCount {
entitiyCount(type: String): Int
}
interface HasSubEntities {
entities(
type: String
): [Entity!]
}
interface HasMachines {
machines: [Machine!]
}
interface Entity {
id: ID!
name: String!
type: String!
}
The below works, but I really want to avoid a single type with lots of optional / null fields:
type Entity {
id: ID!
name: String!
type: String!
# Below is what I want to avoid, by using interfaces
# Imagine how this would grow
entityCount
machineCount
entities
machines
}
In my own logic I don't care what the entities are called, only what fields expected. I'd like to avoid a single Entity type with alot of nullable fields on it, so I thought interfaces or unions would be helpful for keeping things separated so I ended up with HasSubEntities, HasEntityCount, HasMachineCount and HasMachines since the bottom entity will not have entities below, and only the bottom entity will have machines. But in the real code there would be much more than the 2, and it could end up with a lot of optional fields, if not utilizing interfaces or unions in some way I think.
There's two separate problems here.
One, GraphQL resolves fields in a top down fashion. Parent fields are always resolved before any children fields. So it's never possible to access the value that a field resolved to from the parent field's resolver (or a "sibling" field's resolver). In the case of fields with an abstract type, this applies to type resolvers as well. A field type will be resolved before any children resolvers are called. The only way to get around this issue is to move the relevant logic from the child resolver to inside the parent resolver.
Two, assuming the somethings field has the type Something (or [Something], etc.), the query you're trying to run will never work because HasBarCount and HasBazCount are not subtypes of Something. When you tell GraphQL that a field has an abstract type (an interface or a union), you're saying that what's returned by the field could be one of several object types that will be narrowed down to exactly one object type at runtime. The possible types are either the types that make up the union, or types that implement the interface.
A union may only be made up of object types, not interfaces or other unions. Similarly, only an object type may implement an interface -- other interfaces or unions may not implement interfaces. Therefore, when using inline fragments with a field that returns an abstract type, the on condition for those inline fragments will always be an object type and must be one of the possible types for the abstract type in question.
Because this is pseudocode, it's not really clear what business rules or use case you're trying to model with this sort of schema. But I can say that there's generally no need to create an interface and have a type implement it unless you're planning on adding a field in your schema that will have that interface as its type.
Edit: At a high level, it sounds like you probably just want to do something like this:
type Query {
entities(type: String!): [Entity!]!
}
interface Entity {
type: String!
# other shared entity fields
}
type EntityWithChildren implements Entity {
type: String!
children: [Entity!]!
}
type EntityWithModels implements Entity {
type: String!
models: [Model!]!
}
The type resolver needs to check for whether we have models, so you'll want to make sure you fetch the related models when you fetch the entity (as opposed to fetching them inside the models resolver). Alternatively, you may be able to add some kind of column to your db that identifies an entity as the "lowest" in the hierarchy, in which case you can just use this property instead.
function resolveType (obj) {
return obj.models ? 'EntityWithModels' : 'EntityWithChildren'
}
Now your query looks like this:
entities {
type
... on EntityWithModels {
models { ... }
}
... on EntityWithChildren {
children {
... on EntityWithModels {
models { ... }
}
... on EntityWithChildren {
# etc.
}
}
}
}
The counts are a bit trickier because of the variability in the entity names and the variability in the depth of the hierarchy. I would suggest just letting the client figure out the counts once it gets the whole graph from the server. If you really want to add count fields, you'd have to have fields like childrenCount, grandchildrenCount, etc. Then the only way to populate those fields correctly would be to fetch the whole graph at the root.

How do I store a comma-separated list in Orchard CMS?

Using Orchard CMS, I am dealing with a record and a part proxy, but cannot figure out how to save it into the DB. In fact, I confess I don't even know how to get the items I'm trying to save into this paradigm. I was originally using enum's for choices:
MyEmum.cs:
public enum Choices { Choice1, Choice2, Choice3, Choice4 }
MyRecord.cs:
public virtual string MyProperty { get; set; }
MyPart.cs:
public IEnumerable<string> MyProperty
{
get
{
if (String.IsNullOrWhiteSpace(Record.MyProperty)) return new string[] { };
return Record
.MyProperty
.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries)
.Select(r => r.Trim())
.Where(r => !String.IsNullOrEmpty(r));
}
set { Record.MyProperty = value == null ? null : String.Join(",", value); }
}
Now, in my service class, I tried something like:
public MyPart Create(MyPartRecord record)
{
MyPart part = Services.ContentManager.Create<MyPart>("My");
...
part.MyProperty = record.MyProperty; //getting error here
...
return part;
}
However, I am getting the following error: Cannot implicitly convert 'string' to System.Collections.Generic.IEnumerable<string>'
Essentially, I am trying to save choices from a checkboxlist (one or more selections) as a comma-separated list in the DB.
And this doesn't even get me over the problem of how do I use the enum. Any thoughts?
For some background:
I understand that the appropriate way to handle this relationship would be to create a separate table and use IList<MyEnum>. However, this is a simple list that I do not intend to manipulate with edits (in fact, no driver is used in this scenario as I handle this on the front-end with a controller and routes). I am just capturing data and redisplaying it in the Admin view for statistical/historical purposes. I may even consider getting rid of the Part (considering the following post: Bertrand's Blog Post.
It should be:
part.MyProperty = new[] {"foo", "bar"};
for example. The part's setter will store the value on the record's property as a comma-separated string, which will get persisted into the DB.
If you want to use enum values, you should use the Parse and ToString APIs that .NET provide on Enum.

Resources