From 49502fd8fc055fddfaff0b595303eb25e9542b52 Mon Sep 17 00:00:00 2001 From: Martin Fenner Date: Sat, 29 Jun 2019 19:53:45 +0200 Subject: [PATCH] graphql support for researchers --- app/graphql/types/query_type.rb | 18 ++++++++++--- .../researcher_connection_with_meta_type.rb | 14 ++++++++++ ...rcher_dataset_connection_with_meta_type.rb | 4 +-- app/graphql/types/researcher_edge_type.rb | 5 ++++ ...r_publication_connection_with_meta_type.rb | 4 +-- ...cher_software_connection_with_meta_type.rb | 4 +-- app/graphql/types/researcher_type.rb | 26 ++++++++++++++----- 7 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 app/graphql/types/researcher_connection_with_meta_type.rb create mode 100644 app/graphql/types/researcher_edge_type.rb diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index d567f97e9..62dc119ba 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -81,15 +81,21 @@ def funder(id:) result end - field :researcher, ResearcherType, null: false do + field :researcher, ResearcherType, null: true do argument :id, ID, required: true end def researcher(id:) - result = Researcher.find_by_id(id).fetch(:data, []).first - fail ActiveRecord::RecordNotFound if result.nil? + ElasticsearchLoader.for(Researcher).load(orcid_from_url(id)) + end - result + field :researchers, ResearcherConnectionWithMetaType, null: false, connection: true, max_page_size: 100 do + argument :query, String, required: false + argument :first, Int, required: false, default_value: 25 + end + + def researchers(query: nil, first: nil) + Researcher.query(query, page: { number: 1, size: first }).results.to_a end field :organizations, OrganizationConnectionWithMetaType, null: false, connection: true, max_page_size: 100 do @@ -428,4 +434,8 @@ def doi_from_url(url) uri.path.gsub(/^\//, "").downcase end end + + def orcid_from_url(url) + Array(/\A(http|https):\/\/orcid\.org\/(.+)/.match(url)).last + end end diff --git a/app/graphql/types/researcher_connection_with_meta_type.rb b/app/graphql/types/researcher_connection_with_meta_type.rb new file mode 100644 index 000000000..71d05ee8b --- /dev/null +++ b/app/graphql/types/researcher_connection_with_meta_type.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class ResearcherConnectionWithMetaType < BaseConnection + edge_type(ResearcherEdgeType) + field_class GraphQL::Cache::Field + + field :total_count, Integer, null: false, cache: true + + def total_count + args = object.arguments + + Researcher.query(args[:query], page: { number: 1, size: 0 }).results.total + end +end diff --git a/app/graphql/types/researcher_dataset_connection_with_meta_type.rb b/app/graphql/types/researcher_dataset_connection_with_meta_type.rb index 4b937afe0..4ac1f6663 100644 --- a/app/graphql/types/researcher_dataset_connection_with_meta_type.rb +++ b/app/graphql/types/researcher_dataset_connection_with_meta_type.rb @@ -7,12 +7,12 @@ class ResearcherDatasetConnectionWithMetaType < BaseConnection field :total_count, Integer, null: false, cache: true def total_count - Event.query(nil, obj_id: https_to_http(object.parent[:id]), citation_type: "Dataset-Person").results.total + Event.query(nil, obj_id: https_to_http(object.parent.uid ? "https://orcid.org/#{object.parent.uid}" : nil || object.parent[:id]), citation_type: "Dataset-Person").results.total end def https_to_http(url) uri = Addressable::URI.parse(url) - uri.scheme = "http" + uri.scheme = "http" if uri.present? uri.to_s end end diff --git a/app/graphql/types/researcher_edge_type.rb b/app/graphql/types/researcher_edge_type.rb new file mode 100644 index 000000000..6504fafcd --- /dev/null +++ b/app/graphql/types/researcher_edge_type.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class ResearcherEdgeType < GraphQL::Types::Relay::BaseEdge + node_type(ResearcherType) +end diff --git a/app/graphql/types/researcher_publication_connection_with_meta_type.rb b/app/graphql/types/researcher_publication_connection_with_meta_type.rb index b10589ef9..64ff0640c 100644 --- a/app/graphql/types/researcher_publication_connection_with_meta_type.rb +++ b/app/graphql/types/researcher_publication_connection_with_meta_type.rb @@ -7,12 +7,12 @@ class ResearcherPublicationConnectionWithMetaType < BaseConnection field :total_count, Integer, null: false, cache: true def total_count - Event.query(nil, obj_id: https_to_http(object.parent[:id]), citation_type: "Person-ScholarlyArticle").results.total + Event.query(nil, obj_id: https_to_http(object.parent.uid ? "https://orcid.org/#{object.parent.uid}" : nil || object.parent[:id]), citation_type: "Person-ScholarlyArticle").results.total end def https_to_http(url) uri = Addressable::URI.parse(url) - uri.scheme = "http" + uri.scheme = "http" if uri.present? uri.to_s end end diff --git a/app/graphql/types/researcher_software_connection_with_meta_type.rb b/app/graphql/types/researcher_software_connection_with_meta_type.rb index 2a95d0b1e..6880cd9d9 100644 --- a/app/graphql/types/researcher_software_connection_with_meta_type.rb +++ b/app/graphql/types/researcher_software_connection_with_meta_type.rb @@ -7,12 +7,12 @@ class ResearcherSoftwareConnectionWithMetaType < BaseConnection field :total_count, Integer, null: false, cache: true def total_count - Event.query(nil, obj_id: https_to_http(object.parent[:id]), citation_type: "Person-SoftwareSourceCode").results.total + Event.query(nil, obj_id: https_to_http(object.parent.uid ? "https://orcid.org/#{object.parent.uid}" : nil || object.parent[:id]), citation_type: "Person-SoftwareSourceCode").results.total end def https_to_http(url) uri = Addressable::URI.parse(url) - uri.scheme = "http" + uri.scheme = "http" if uri.present? uri.to_s end end diff --git a/app/graphql/types/researcher_type.rb b/app/graphql/types/researcher_type.rb index 8e89257fa..a63e86367 100644 --- a/app/graphql/types/researcher_type.rb +++ b/app/graphql/types/researcher_type.rb @@ -9,38 +9,50 @@ class ResearcherType < BaseObject field :given_name, String, null: true, hash_key: "givenName", description: "Researcher given name" field :family_name, String, null: true, hash_key: "familyName", description: "Researcher family name" field :affiliation, [String], null: true, description: "Researcher affiliation" - field :datasets, ResearcherDatasetConnectionWithMetaType, null: false, description: "Authored datasets", connection: true, max_page_size: 100 do + field :datasets, ResearcherDatasetConnectionWithMetaType, null: true, description: "Authored datasets", connection: true, max_page_size: 100 do argument :first, Int, required: false, default_value: 25 end - field :publications, ResearcherPublicationConnectionWithMetaType, null: false, description: "Authored publications", connection: true, max_page_size: 100 do + field :publications, ResearcherPublicationConnectionWithMetaType, null: true, description: "Authored publications", connection: true, max_page_size: 100 do argument :first, Int, required: false, default_value: 25 end - field :softwares, ResearcherSoftwareConnectionWithMetaType, null: false, description: "Authored software", connection: true, max_page_size: 100 do + field :softwares, ResearcherSoftwareConnectionWithMetaType, null: true, description: "Authored software", connection: true, max_page_size: 100 do argument :first, Int, required: false, default_value: 25 end def id - object.fetch(:id, nil) || object.fetch("nameIdentifiers", []).find { |n| n.fetch("nameIdentifierScheme", nil) == "ORCID" }.to_h.fetch("nameIdentifier", nil) + object.uid ? "https://orcid.org/#{object.uid}" : nil || object.fetch(:id, nil) || object.fetch("nameIdentifiers", []).find { |n| n.fetch("nameIdentifierScheme", nil) == "ORCID" }.to_h.fetch("nameIdentifier", nil) + end + + def name + object.name || object.fetch("name", nil) + end + + def given_name + object.given_names || object.fetch("givenName", nil) + end + + def family_name + object.family_name || object.fetch("familyName", nil) end def datasets(**args) - ids = Event.query(nil, obj_id: https_to_http(object[:id]), citation_type: "Dataset-Person").results.to_a.map do |e| + ids = Event.query(nil, obj_id: https_to_http(object.uid ? "https://orcid.org/#{object.uid}" : nil || object[:id]), citation_type: "Dataset-Person").results.to_a.map do |e| doi_from_url(e.subj_id) end ElasticsearchLoader.for(Doi).load_many(ids) end def publications(**args) - ids = Event.query(nil, obj_id: https_to_http(object[:id]), citation_type: "Person-ScholarlyArticle").results.to_a.map do |e| + ids = Event.query(nil, obj_id: https_to_http(object.uid ? "https://orcid.org/#{object.uid}" : nil || object[:id]), citation_type: "Person-ScholarlyArticle").results.to_a.map do |e| doi_from_url(e.subj_id) end ElasticsearchLoader.for(Doi).load_many(ids) end def softwares(**args) - ids = Event.query(nil, obj_id: https_to_http(object[:id]), citation_type: "Person-SoftwareSourceCode").results.to_a.map do |e| + ids = Event.query(nil, obj_id: https_to_http(object.uid ? "https://orcid.org/#{object.uid}" : nil || object[:id]), citation_type: "Person-SoftwareSourceCode").results.to_a.map do |e| doi_from_url(e.subj_id) end ElasticsearchLoader.for(Doi).load_many(ids)