Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use GraphQL

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the knowledge of "how to use GraphQL". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

GraphQL comes with a set of default scalar types

Int: signed 32-bit integer.

Float: signed double-precision floating-point value.

String:UTF-8 character sequence.

Boolean:true or false.

The ID:ID scalar type represents a unique identifier that is usually used to retrieve an object or as a key in the cache. The ID type is serialized in the same way as String; however, defining it as ID means that there is no need for human readability.

For the code, see gitee Warehouse example

GraphQL operation type

Query query

Mutation mutation (understood as modification)

Subscription script

Dgs Custom scalar

Implement interface Coercing

Add annotation @ DgsScalar example

@ DgsScalar (name = "Date") public class DateCoercing implements Coercing {private static final String PATTERN = "yyyy-MM-dd HH:mm:ss"; @ Override public String serialize (Object o) throws CoercingSerializeException {if (o instanceof Date & & Objects.nonNull (o)) {Date date = (Date) o; SimpleDateFormat sdf = new SimpleDateFormat (PATTERN); return sdf.format (date);} return null } @ Override public Date parseValue (Object o) throws CoercingParseValueException {if (o instanceof Date & & Objects.nonNull (o)) {return (Date) o;} else {throw new CoercingParseValueException ("type is not date") } @ Override public Date parseLiteral (Object o) throws CoercingParseLiteralException {if (o instanceof String & & Objects.nonNull (o)) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern (PATTERN); LocalDateTime localDateTime = LocalDateTime.parse (o.toString (), formatter); return Date.from (localDateTime.atZone (ZoneId.systemDefault ()). ToInstant ());} return null } .graphql configure type Show {title: String releaseYear: Int now: Date} scalar Date

Postman access

Alias

When two query names conflict at the same time, you can use aliases to get different results

{zhangsan: hello (name: "Zhang San"), lisi: hello (name: "Li Si")} output: {"data": {"zhangsan": "hello: Zhang San!", "lisi": "hello: Li Si!"}} fragment (fragment)

Fragments are mainly used to encapsulate multiple identical fields. In actual development, we will encounter many fields with the same names in the returned results, which are defined in the .graphql file using = = fragment==.

{golang: shows (title: "golang") {... showFields}, java: shows (title: "java") {... showFields}} # definition fragment fragment showFields on Show {title releaseYear now} output {"data": {"golang": [{"title": "golang", "releaseYear": 2009 "now": "2021-03-08 13:46:43"}], "java": [{"title": "java", "releaseYear": 1995, "now": "2021-03-08 13:46:43"}]}}

The types after the above on must be defined in the .graphql file

The use of multiple .graphqls

Custom address.graphqls

# multiple .graphqls definitions need to use this method extend type Query {listAddress (id: Int): Address} extend type Mutation {addAddress (input: AddressInput): Int} type Address {id: Int street: String city: String country: String customerId: Int} input AddressInput {street: String city: String country: String customerId: Int}

Other custom schema file queries need to use type extend specific type method

Mutation

Mutation is used to modify objects, matters needing attention when using dgs

ParentType= "Mutation" in @ DgsData, field needs to be consistent with that in schema

When the object type is defined in java, it needs to be defined in the corresponding .graphqls file. The type is input.

Input AddressInput {street: String city: String country: String customerId: Int}

Objects in the graphiql query page are defined in variables

Example of query input box add object format pass parameter mutation AddAddress ($addAddress: AddressInput) {addAddress (input: $addAddress)} modified request parameter directly pass the variable value in mutation UpdateAddress {updateAddress (id: 1, street: "Fengyang Street", city: "Guangzhou") {id street city customerId}} query variables {"addAddress": {"street": "Jianghai Street" "city": "Guangzhou", "country": "China", "customerId": 1}}

Multiple fields in a change (Multiple fields in mutations) A change can also contain multiple fields, just like a query. An important difference between a query and a change name is:

Non-variable definition mode

Mutation AddAddress1 {addAddress (input: {street: "Changgang Street", city: "Guangzhou", country: "China", customerId: 1})}! [] (https://gitee.com/sharehappy/figurebed/raw/master/md/img/2021/04/20210421183524.png)

When querying fields, they are executed in parallel, while when fields are changed, they are executed linearly, one after another.

Operation name

Above, we mainly query, omitting the query keyword and query name, which can reduce code ambiguity in production.

Query Abc {hello (name: "zhangsan")} mutation AddAddress ($addAddress: AddressInput) {addAddress (input: $addAddress)} mutation UpdateAddress {updateAddress (id: 1, street: "Fengyang Street", city: "Guangzhou") {id street city customerId}}

The operation type can be query, mutation, or subscription, which describes what type of operation you intend to do. The action type is required unless you use query shorthand syntax, in which case you cannot provide a name or variable definition for the operation.

The operation name is the meaningful and explicit name of your operation. It is only necessary in documents with multiple operations, but we encourage it because it is useful for debugging and server-side logging. When there is a problem with your network or GraphQL server logs, it is easier to find a query from your code base by name than to try to decipher the content. Just think of it as a function name in your favorite programming language.

Variable (Variables)

The previous queries are based on multiple parameters. In order to expand and reduce the modification code, we usually encapsulate multiple parameters into objects. GraphQL has a first-level method to extract dynamic values out of the query and pass them in as a separate dictionary. These dynamic values are called variables.

Before we can use variables, we have to do three things:

Replace the static value in the query with $variableName.

Declare $variableName as one of the variables accepted by the query.

Put variableName: value in a separate variable dictionary that transmits a dedicated (usually JSON).

Example:

Add the variable mutation AddAddress ($addAddress: AddressInput) {addAddress (input: $addAddress)} the actual variable value in the input box {"addAddress": {"street": "Jianghai Street", "city": "Guangzhou", "country": "China", "customerId": 1}} variable definition (Variable definitions)

The variable definition looks like the one in the above query ($addAddress: AddressInput). It works the same way as the parameter definition of a function in a typed language. It lists all variables, which must be prefixed with $, followed by their type, in this case AddressInput.

All declared variables must be scalar, enumerated, or input object types. So if you want to pass a complex object to a field, you must know the type of match on the server. You can learn more about input object types from the Schema page.

Variable definitions can be optional or necessary. In the above example, there is no! after AddressInput, so it is optional. But if you pass a field of a variable that requires a non-empty parameter, the variable must be necessary.

Default variable (Default variables)

You can assign default values to variables by appending default values to the type definition in the query.

Query HeroNameAndFriends ($episode: Episode = "JEDI") {hero (episode: $episode) {name friends {name}

When all variables have default values, you can call the query without passing variables. If any variable is passed as part of the variable dictionary, it overrides its default value.

Instruction (Directives)

Instructions can be used to dynamically control whether a field is displayed. In some scenarios, we may need to use the An attribute of the object, while in some scenarios, we do not need the An attribute, so we can use instructions to control it.

Query movies ($withDirector: Boolean!) {movies {title director @ skip (if: $withDirector) actor @ include (if: $withDirector) {name} actor {home}} variable {"withDirector": false}

The value of the variable is true. The value of the variable is false. You can use @ skip for field operations and @ include for some properties in the object.

We used a new feature in GraphQL called instructions. An instruction can be attached to a field or a field contained in a fragment, and then change the execution of the query in any way expected by the server. The core specification of GraphQL contains two directives that must be supported by any specification-compliant GraphQL server implementation:

@ include (if: Boolean) includes this field only if the parameter is true.

@ skip (if: Boolean) skips this field if the parameter is true. The instruction rescues you when you have to add or subtract the fields of the query through string operations. The server-side implementation can also define new instructions to add new features.

Inline fragment (inline fragment)

If the field you are querying returns an interface or federation type, you may need to use inline fragments to fetch the specific types of data below:

/ * the inline segment * @ param filter * @ return * / @ DgsData (parentType = "Query", field = "movieFilter") public List movieFilter (@ InputArgument ("filter") MovieType filter) {return initMovie (filter);} private List initMovie (MovieType movieType) {List movies = new ArrayList (); Actor actor1 = new Actor (); actor1.setHome ("Guangzhou") is used in graphql according to the enumeration type. Actor1.setName ("Zhang San"); Actor actor2 = new Actor (); actor2.setHome ("Shanghai"); actor2.setName ("Li Si"); if (movieType.equals (MovieType.Action) | | movieType.equals (MovieType.All)) {movies.add ("Crouching Tiger", null, 0, actor1); movies.add (new ActionMovie ("Black hawk down", null, 10, actor1)) } if (movieType.equals (MovieType.Scary) | | movieType.equals (MovieType.All)) {movies.add (new ScaryMovie ("American Horror Story", null, true, 10, actor2)); movies.add (new ScaryMovie ("Love Death + Robots", null, false, 4, actor2));} return movies;}

Schema

# define enumerated enum MovieType {Scary Action All} type Query {movieFilter (filter: MovieType): [Movie]} graphiql queries

Meta field (Meta fields)

In some cases, you don't know what type you will get from the GraphQL service, so you need some methods on the client side to decide what to do with the data. GraphQL allows you to request _ _ typename, a meta-field, anywhere in the query to get the object type name at that location

Schema and type enumeration

An enumerated type is a special scalar that is limited to a special set of optional values.

Verify that any parameter of this type is one of the optional values

In communication with the type system, a field is always one of the values of a finite set of values.

Enum Episode {NEWHOPE EMPIRE JEDI} Interface (Interfaces)

Like many types of systems, GraphQL supports interfaces. An interface is an abstract type that contains certain fields, and the object type must contain these fields in order to implement the interface.

Interface Movie {title: String director: String actor: Actor} type ScaryMovie implements Movie {title: String director: String gory: Boolean scareFactor: Int actor: Actor} type ActionMovie implements Movie {title: String director: String nrOfExplosions: Int actor: Actor} Union Type (union)

A federated type is very similar to an interface, but it does not specify any common fields between types.

Union MovieResult = ScaryMovie | ActionMovie

In our schema, wherever a MovieResult type is returned, you may get a ScaryMovie, ActionMovie p. Note that members of federated types need to be specific object types; you cannot use interfaces or other federated types to create a federated type.

At this point, if you need to query a field that returns the SearchResult union type, you have to use conditional fragments to query any field.

Schema# union union type movieFilter (filter: MovieType): [MovieResult] query query Movie ($filter: MovieType!) {movieFilter (filter: $filter) {_ _ typename. On ScaryMovie {scareFactor title director actor {name home}}... On ActionMovie {nrOfExplosions title director actor {name home}

Union type can be understood as a combination of different types of data returned according to different parameters, which is slightly different from the interface. You can compare schema and query results.

Instrumentation in graph-java

Implement instrumentation interface or inherit SimpleInstrumentation for log and permission processing, similar to aop in spring

@ Configurationpublic class GraphQLConfig {@ Bean @ Primary public Instrumentation instrumentation () {Instrumentation instrumentation = new ChainedInstrumentation (new TracingInstrumentation (), new CustomInstrumentation ()); return instrumentation;}}

The @ Primary is added because there is a corresponding bean injection in DgsAutoConfiguration.kt

Pagination

Paging in graphql can only know whether there is a next page of data, but cannot get the total amount and the current page. This result can be combined with dataLoader cache to scroll through the page schema.graphqls according to the conditional query.

# type AddressConnection {edges: [AddressEdge] pageInfo: PageInfo} type AddressEdge {cursor: String node: Address} type PageInfo {hasPreviousPage: Boolean! HasNextPage: Boolean!} / * * paging query * @ param environment * @ param customerId query condition * @ how many results * @ param after each piece of data has a cursor, and several pieces of data after the current cursor are used with first Null starts from the first * @ param last how many pieces of data * @ param before several pieces of data in front of the current cursor are used with last Null starts with the last entry * @ return * / @ DgsData (parentType = "Query", field = "pageAddress") public Connection pageAddress (DataFetchingEnvironment environment, @ InputArgument ("customerId") Integer customerId, @ InputArgument ("first") Integer first, @ InputArgument ("after") String after, @ InputArgument ("last") Integer last InputArgument ("before") String before) {List addressList = addressMapper.selectList (Wrappers.lambdaQuery () .eq (Address::getCustomerId, customerId)) Return new SimpleListConnection (addressList) .get (environment);}

This is the end of "how to use GraphQL". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report