見出し画像

ServiceNow GraphQL: 条件を指定してクエリできるようにする

基本ができたのでもっと色々作り込んでみよう。

日付データフォーマット

こちらの記事で日付データフォーマットがうまく扱えずにスキップしたんですが、謎が解けました。

そもそもGraphQLにDate型が定義されていませんでした。

In most GraphQL service implementations, there is also a way to specify custom scalar types. For example, we could define a Date type:

Schemas and Types (GraphQL)

つまりDate型を実装したい場合は必ずカスタムで設定することになります。

先日遊んだGraphQL検証用アプリ (GraphQL Framework Demo Application plugin) のスキーマ定義をよく見るとあるじゃないですか。

type Date { 
    year: Int!
    month: Int!
    day: Int!
    hours: Int
    minutes: Int
}

じゃあ何もしないとどんなデータが来るのか。
Stringに仮置きしてレコードの最終更新日時を取得すると、デフォルトのフォーマットは [yyyy-MM-dd HH:mm:ss] であることがわかります。
これはServiceNowのライブラリの仕様どおり。

したがってデータを出すだけと言う目的に特化するなら、Stringで取得すれば出力できます。例えば

lastupdated: String @source(value: "sys_updated_on")

なんとなくカッコ悪いのでDateを使いたいのですが、残念ながらDate型は現在のServiceNowでは使えないようです。
GraphQLのSchemas and Typesによると

scalar Date

と宣言してResolverの中で定義すればいいようなのですが、ServiceNowの製品マニュアル (San Diego) によるとカスタムスカラータイプはサポートされていないそうです。

条件をクエリから指定しよう

既に作ったフィールドでは検索条件はリクエストないでは受け付けず、必ず指定の条件でデータを取得するようにしました。
今度はステータスの値をリクエストを送信する側が指定できるようにします。

フィールドの指定に booksbystatus を追加、ステータスを指定できるようにしました。

type Query {
	availablebooks: [Books]
	booksbystatus(status: String!): [Books]
	datetest: [DateTest]
}

以下Resolver。

(function process(/*ResolverEnvironment*/ env) {

    var status = env.getArguments().status;
	var books = new GlideRecord('x_805160_my_books_mybooks');
	
	books.addQuery('status', status);
	books.query();
	
    return books;

})(env);

enum も使ってみよう

Statusの値は

  • Interested

  • Purchased

  • Available

しかないので、スキーマ側で指定してみます。

enum Status {
	Interested
	Purchased
	Available
}

オブジェクト Books の設定上もenumで設定したStatusに変更。

type Books {
	id: ID! @source(value: "sys_id.display_value")
	number: String! @source(value: "number.display_value")
	name: String @source(value: "name.display_value")
	author: String @source(value: "author.display_value")
	publisher: String @source(value: "publisher.display_value")
	description: String @source(value: "description.display_value")
	status: Status @source(value: "status.display_value")
}

クエリを送ってみると大文字小文字区別していることがわかります。
わざと小文字で送ってみる。
enumなので条件分のところのクォーテーションマークは不要。

query {
  x805160MyBooks {
    mytestschema {
      booksbystatus(status: available) {
        id
        number
        status
      }
    }
  }
}

レスポンスはエラー。

{
  "data": null,
  "errors": [
    {
      "message": "Validation error of type WrongType: argument 'status' with value 'EnumValue{name='available'}' is not a valid 'x805160MyBooks_mytestschema_Status' - Expected enum literal value not in allowable values -  'EnumValue{name='available'}'. @ 'x805160MyBooks/mytestschema/booksbystatus'",
      "errorType": "ValidationError",
      "locations": [
        {
          "line": 4,
          "column": 21
        }
      ],
      "validationErrorType": "WrongType"
    }
  ]
}

大文字小文字も合致すればちゃんとレスポンスが返ってくる。
リクエスト。

query {
  x805160MyBooks {
    mytestschema {
      booksbystatus(status: Available) {
        id
        number
        status
      }
    }
  }
}

レスポンス。

{
  "data": {
    "x805160MyBooks": {
      "mytestschema": {
        "booksbystatus": [
          {
            "id": "156e8e7a1b3ec110b66f55f0604bcba0",
            "number": "MYB0001002",
            "status": "Available"
          },
          {
            "id": "3dce86f21b7ec110b66f55f0604bcb57",
            "number": "MYB0001004",
            "status": "Available"
          },
          {
            "id": "6bcfcef21b7ec110b66f55f0604bcba0",
            "number": "MYB0001005",
            "status": "Available"
          }
        ]
      }
    }
  }
}

もっと複雑なクエリも自分で実装できる!

今までクエリは合致するもので実装してきたけれども、GraphQLそのものはもっと複雑なクエリを実装できることも知ってます。

少し前に試したサンプルアプリでは、日付の指定にDateInputというオブジェクトを作成し、開始日と終了日を指定させることで日付の比較をしてデータを取り出していました。
スキーマとコードの合わせ技ならなんでもできる!

どこまで複雑にできるかというと、例えばGithubにあるサンプルでは相当複雑なことをやっています。
スキーマとコードの組み合わせで割となんでもできる!

このサンプルのAllIncidentでは、ページ送り、ソート、複雑な条件の指定などがスキーマに記述されています。


この記事が気に入ったらサポートをしてみませんか?