MI-DPLA / combine

Combine /kämˌbīn/ - Metadata Aggregator Platform
MIT License
26 stars 11 forks source link

adding graphql endpoint #412

Open ghukill opened 5 years ago

ghukill commented 5 years ago

Might obviate: https://github.com/MI-DPLA/combine/issues/106.

Currently in graphql branch.

Scaffolding GraphQL endpoint for Combine that would provide structured data requests for disparate models. Working prototype in place for some Django models, exploring how to incorporate data from Mongo and ElasticSearch in the graphql endpoint as well.

Using graphene-django, setup and dependencies are minimal, with a GraphiQL view for free.

While the data may be queried and consumed outside of the Django app context, it might also eventually find use internally for the front-end views.

ghukill commented 5 years ago

Still exploratory, but proof of concept encouraging.

GraphQL query at /graphiql accessing single Job by id, Records from that Job limited by first 5, and select mapped fields for those Records:

{
  job(id:209) {
    id
    all_records(first: 5) {
      id
      mods_abstract: mapped_field(field_name: "mods_abstract")
      mods_subject_topic: mapped_field(field_name: "mods_subject_topic")
    }
  }
}

Payload:

{
  "data": {
    "job": {
      "id": "209",
      "all_records": [
        {
          "id": "5d00e643e60a100055e37f4d",
          "mods_abstract": [
            "Image of the corner the Globe Trading Company building, also known as the Dry Dock Complex, at the corner of Woodbridge and Orleans Streets.  This location is approximately five blocks from the Renaissance Center construction site.  The Dry Dock Complex consisted of six interconnected buildings located at 1801-1803 Atwater Street."
          ],
          "mods_subject_topic": [
            "Construction industry"
          ]
        },
        {
          "id": "5d00e643e60a100055e37f4e",
          "mods_abstract": [
            "Image of the progress of construction of the Renaissance Center towers.  Note the cement trucks and other equipment at the base of the buildings."
          ],
          "mods_subject_topic": [
            "Construction industry",
            "Construction equipment",
            "Scaffolding",
            "Cranes, derricks, etc."
          ]
        },
        {
          "id": "5d00e643e60a100055e37f4f",
          "mods_abstract": [
            "Image of Ford Auditorium, which opened in 1956 and was demolished in 2011.  This photograph, taken from Jefferson Avenue and Woodward Avenue, shows the auditorium was just south of the Renaissance Center."
          ],
          "mods_subject_topic": [
            "Construction industry",
            "Construction equipment",
            "Scaffolding"
          ]
        },
        {
          "id": "5d00e643e60a100055e37f50",
          "mods_abstract": [
            "Image of unidentified buildings in the vicinity of the Renaissance Center construction site."
          ],
          "mods_subject_topic": [
            "Construction industry"
          ]
        },
        {
          "id": "5d00e643e60a100055e37f51",
          "mods_abstract": [
            "Image of the progress on one of the four towers of the Renaissance Center. Clearing seen are derricks and scaffolding."
          ],
          "mods_subject_topic": [
            "Construction industry",
            "Construction equipment",
            "Scaffolding",
            "Cranes, derricks, etc."
          ]
        }
      ]
    }
  }
}
ghukill commented 5 years ago

Rough example of looping through mapped fields in a CombineJob instance and crafting a graphql query issued with requests:

# get CombineJob
cjob = CombineJob.get_combine_job(209)

# query base
query_base = '''query {
  job(id:%(job_id)s) {
    id
    all_records(first:10) {
      id
      %(fields)s
    }
  }
}'''

# prepare fields
fields = [ '%(field_name_san)s: mapped_field(field_name: "%(field_name)s")' % {'field_name_san':field['field_name'].replace('@','').replace('=',''), 'field_name':field['field_name']} for field in cjob.mapped_fields_analysis().get('fields') ]

# add to query base
query = query_base % {'job_id':cjob.job.id, 'fields':'\n'.join(fields)}

# query
r = requests.get('http://localhost:8000/combine/graphql', json={'query':query}).json()

Or, executing that query string with graphene schema instance (much easier):

from core.graphql.schema import schema
schema.execute(query)
result = schema.execute(query)
antmoth commented 5 years ago

We won't necessarily need this as much after moving to Postgres but it would still be some amount useful.