Home > Mobile >  Query data with graphene using custom filters
Query data with graphene using custom filters

Time:06-14

I think I must have missed something basic here so hopefully this will be an easy fix. I've set up my graphql api with graphene and SQLalchemy and I can return all the data from my Postgres database. However, I can't figure out how to limit my results to return only one record.

Here's my schema object:

class Dataset(SQLAlchemyObjectType):
    class Meta:
        model = DatasetModel
        interfaces = (graphene.relay.Node, )

And here's my query:

class Query(graphene.ObjectType):
    node = graphene.relay.Node.Field()
     all_datasets = SQLAlchemyConnectionField(Dataset.connection)

schema = graphene.Schema(query=Query)

What do I need to add/change to allow me to limit the results by the field datasetName?

I tried adding the following function:

def resolve_dataset(root, info, datasetName):
    return db_session.query(Dataset).filter_by(datasetName=datasetName).first()

The API still runs but when I try adding the search field to the graphql query, I get a syntax error. I also tried adding the line:

Base.query = db_session.query_property()

To my models.py as suggested by the documentation but it didn't seem to make any difference.

Can someone explain what I missed? How do I limit my results by a value I supply to the api?

EDIT: Adding in information problem I encountered implementing the first suggested solution.

I added the resolved function below to my query class:

 def resolve_all_datasets(root, info, **kwargs):
    query = db_session.query(Dataset)
    if kwargs.get('datasetName'):
        
query=query.filter_by(datasetName=kwargs['datasetName'])
    return query

And then searched with the following query to my api endpoint:

{allDatasets(datasetName:"MyDataset"){
edges{
node{
  abstract
    }
  }
 }
}

But got:

{
  "errors": [
    {
      "message": "Column expression or FROM clause expected, got <Dataset meta=<SQLAlchemyObjectTypeOptions name='Dataset'>>.",
      "locations": [
        {
          "line": 2,
          "column": 2
        }
      ],
      "path": [
        "allDatasets"
      ]
    }
  ],
  "data": {
    "allDatasets": null
  }
}

CodePudding user response:

You should define resolve_all_datasets resolver instead of resolve_dataset (i cannot see dataset field on your schema). For an elegant solution you can use library:https://pypi.org/project/graphene-sqlalchemy-filter/

However you can override resolver manually:

class Query(graphene.ObjectType):
    node = graphene.relay.Node.Field()
    all_datasets = SQLAlchemyConnectionField(Dataset.connection, datasetName=graphene.String())

    def resolve_all_datasets(root, info, **kwargs):
        query = db_session.query(DatasetModel)
        if kwargs.get('datasetName'):
            query = query.filter_by(datasetName=kwargs['datasetName'])
        return query

schema = graphene.Schema(query=Query)

Alternative solution to return only one dataset:

class Query(graphene.ObjectType):
    node = graphene.relay.Node.Field()
    dataset = graphene.Field(Dataset, datasetName=graphene.String(required=True))

    def resolve_dataset(root, info, **kwargs):
        return db_session.query(DatasetModel).filter_by(datasetName=kwargs['datasetName']).first()

schema = graphene.Schema(query=Query)
  • Related