-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for conditional querying #138
Comments
These are called Take a look at examples at https://sgqlc.readthedocs.io/en/latest/sgqlc.operation.html#selecting-to-generate-queries, in particular look for >>> op.repository(id='repo1').__fields__(
... issues={'title_contains': 'bug'}, # adds field and children
... ) This should also work: >>> op.repository(id='repo1').issues(title_contains='bug') Then in your case, the following should work: op.reviews(where={'id': {'_eq': Variable('some_number') }}).__fields__('id', 'review_text') Two advices:
|
This is what I tried, class Query(Type):
reviews = Field(reviews ,args={'where':dict})
op = Operation(Query)
rating = op.reviews(where={'id':{'_eq': 12}}).__fields__('id','review_text') But it gave me a |
there isn't a mapping to a generic How is your server defining this? You need to use the same types and signatures in the client side, otherwise the server may reject it, in particular if you're using variables, any modifier mismatch will cause errors. If you didn't write the server yet, I recommend you to go explicit and do not try to map a generic JSON object (you can't because all the object keys must be fixed, you'd have to create an array of key-value objects instead). Example schema: input WhereIntRange {
min: Int!
max: Int!
}
input WhereInt {
eq: Int
lt: Int
gt: Int
le: Int
ge: Int
range: WhereIntRange
}
input ReviewsWhere {
id: WhereInt
}
type Query {
reviews(where: ReviewsWhere): [Review!]!
} |
@rohansharmaa I assume you are trying to do the same that I am - using Hasura as a backend. Just use the code generator to generate the "Query" part and then your Operation that you posted above should work fine. So far I've had no trouble integrating sgqlc with Hasura. The code generator works like a charm and I'm successfully running queries. Regarding the syntax, @barbieri thanks for noting that the code generator can transform raw graphql queries to python code! It allows to use the Hasura documentation and GraphiQL to make a query and then see how it should look in gsqlc. |
Let me follow up on the original question. I found that it's possible to write Hasuras dict-like filter queries using the gsqlc syntax. See here two equivalent filter queries:
I am wondering why the codegen doesn't generate the gsql-syntax but instead the dict-syntax? I am wondering which is better to use since the gsql-syntax is more type safe but the dict-syntax is easier to read/write. |
is this still an issue? Also, I highly recommend these kind of parameters to be set via The actual value of the variable you send as a plain Python "JSON-like" object, the server will handle all the needed checks to avoid errors. |
I was on a massive time crunch, so as of now I've manually defined all the queries as a string and using those. Once I find the time to experiment, I'll try out these suggestions and get back to you. |
I love the generated types of sgqlc, because it will not allow me to write a broken query. Basically - if it compiles, it should work. That's great and I tried to apply the thought to Hasuras complex arguments. Do you think it's better not to validate the json argument before sending to the server? |
[PT-BR] [EN] import sgqlc.types
import sgqlc.operation
import hasura_schema
_schema = hasura_schema
_schema_root = _schema.hasura_schema
__all__ = ('Operations',)
def query_my_query():
_op = sgqlc.operation.Operation(_schema_root.query_type, name='MyQuery', variables=dict(order_by=sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(_schema.binance_assets_order_by)), default={'id': 'asc'})))
_op_binance_assets = _op.binance_assets(offset=10, order_by=sgqlc.types.Variable('order_by'))
_op_binance_assets.fk_info_assets_id()
_op_binance_assets.fiat()
return _op
class Query:
my_query = query_my_query()
class Operations:
query = Query
""" AssertionError: 'id' (str) is not a JSON Object """
print(query_my_query())
|
Hi @hungertaker , yes I'm also 🇧🇷 :-) But let's keep it in english so others may read it as well. I need the description of |
in your example, it looks wrong. If that was generated, also send me the operation so I can see what's wrong in my codegen, but: order_by=sgqlc.types.Arg(
sgqlc.types.list_of(sgqlc.types.non_null(_schema.binance_assets_order_by)), # list!
default={'id': 'asc'} # object, not a list...
) If the variable is declared as |
Worked perfectly. Thank you very much. The abstraction you made from graphql to python, in the case of Hasura, which is a mirror of Postgres, allows to consult the entire endpoint, with a few classes. Soon I share with the community here some examples and ideas. |
The query, codegen and schema.binance_assets_order_by: query:query MyQuery($order_by: [binance_assets_order_by!] = {id: asc}) {
binance_assets(offset: 10, order_by: $order_by) {
fk_info_assets_id
fiat
}
} codegenimport sgqlc.types
import sgqlc.operation
import hasura_schema
import json
_schema = hasura_schema
_schema_root = _schema.hasura_schema
__all__ = ('Operations',)
def query_my_query():
_op = sgqlc.operation.Operation(_schema_root.query_type, name='MyQuery', variables=dict(
order_by=sgqlc.types.Arg(sgqlc.types.list_of(
sgqlc.types.non_null(_schema.binance_assets_order_by)),
default={'id': 'asc'}))) # Correct default=[{'id': 'asc'}]
_op_binance_assets = _op.binance_assets(offset=10, order_by=sgqlc.types.Variable('order_by'))
_op_binance_assets.fk_info_assets_id()
_op_binance_assets.fiat()
return _op
class Query:
my_query = query_my_query()
class Operations:
query = Query schema.binance_assets_order_byclass binance_assets_order_by(sgqlc.types.Input):
__schema__ = hasura_schema
__field_names__ = ('fiat', 'fk_info_assets_id', 'id', 'last_update', 'name', 'pairs_by_quote_symbol_id_aggregate', 'pairs_aggregate', 'symbol')
fiat = sgqlc.types.Field(order_by, graphql_name='fiat')
fk_info_assets_id = sgqlc.types.Field(order_by, graphql_name='fk_info_assets_id')
id = sgqlc.types.Field(order_by, graphql_name='id')
last_update = sgqlc.types.Field(order_by, graphql_name='last_update')
name = sgqlc.types.Field(order_by, graphql_name='name')
pairs_by_quote_symbol_id_aggregate = sgqlc.types.Field('binance_pairs_aggregate_order_by', graphql_name='pairsByQuoteSymbolId_aggregate')
pairs_aggregate = sgqlc.types.Field('binance_pairs_aggregate_order_by', graphql_name='pairs_aggregate')
symbol = sgqlc.types.Field(order_by, graphql_name='symbol') |
yes, your query is wrong, I wonder it was passing the checks, but if you try to paste that in GraphiQL/Explorer it should fail. Could you check with the latest master? Now it's doing much more checks and I think it would point out the error. |
Exactly. The query is wrong. I had tested it on Hasura's Graphi and as it passed I thought everything was ok. I generated codegen again with the [...] ones and everything worked out. I'm going to test it on the new master and I'm already giving the feeedback. |
@hungertaker could you confirm the current master reports the incorrect query? |
https://pypi.org/project/sgqlc/14.0/ is released with that fix, so you can use the package. |
I was trying to query a list of objects based on the property of a child object. Is it possible to query selection lists with this syntax? op.repositories(owner='Alice').__fields__(
issues={'title_contains': 'bug'}, # adds field and children
) |
it should be, isn't it working? could you paste the error or at least print the operation and paste the results? Just notice this will only query |
HI, thank you. It is saying that the key doesn't exist. I put it into a colab here. I was using the introspection and code generation (really nice - thank you) and finding the generated filter object with that key for the object I was querying, but maybe the schema isn't implemented to perform that operation? https://colab.research.google.com/drive/1p1UjF4qPLWNPK05s1dMRA34OMEu9ouN-#scrollTo=kGECcPjsQVVk op = Operation(schema.Query)
positions = op.positions(first=2, where={"pool": "0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8"}).__fields__(
tick_upper={"tick_idx_lte": 200000}
)
endpoint(op)
I also tried this formulation: op = Operation(schema.Query)
op.positions(
first=2,
where={"pool": "0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8", "tick_upper": {"tick_idx_lte": 200000}}
)
endpoint(op) and got back this error:
|
Well, I just did the introspection here and checked it, you can search for class Position_filter(sgqlc.types.Input):
# ...
tick_upper = sgqlc.types.Field(String, graphql_name='tickUpper')
tick_upper_not = sgqlc.types.Field(String, graphql_name='tickUpper_not')
tick_upper_gt = sgqlc.types.Field(String, graphql_name='tickUpper_gt')
tick_upper_lt = sgqlc.types.Field(String, graphql_name='tickUpper_lt')
tick_upper_gte = sgqlc.types.Field(String, graphql_name='tickUpper_gte')
tick_upper_lte = sgqlc.types.Field(String, graphql_name='tickUpper_lte')
tick_upper_in = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name='tickUpper_in')
tick_upper_not_in = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name='tickUpper_not_in')
tick_upper_contains = sgqlc.types.Field(String, graphql_name='tickUpper_contains')
tick_upper_not_contains = sgqlc.types.Field(String, graphql_name='tickUpper_not_contains')
tick_upper_starts_with = sgqlc.types.Field(String, graphql_name='tickUpper_starts_with')
tick_upper_not_starts_with = sgqlc.types.Field(String, graphql_name='tickUpper_not_starts_with')
tick_upper_ends_with = sgqlc.types.Field(String, graphql_name='tickUpper_ends_with')
tick_upper_not_ends_with = sgqlc.types.Field(String, graphql_name='tickUpper_not_ends_with') You can confirm in JSON: {
"defaultValue": null,
"description": null,
"name": "tickUpper",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"defaultValue": null,
"description": null,
"name": "tickUpper_not",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}, The only occurrence of {
"defaultValue": null,
"description": null,
"name": "tickIdx_lte",
"type": {
"kind": "SCALAR",
"name": "BigInt",
"ofType": null
}
}, And |
Thanks for taking a look and that helps for looking at the schema to see what is possible in the future. Looks like the filter I need is not implemented. |
Sorry, I'm new to this.
Is there a way to generate conditional queries like -
I'm only asking about the "where: { id : { _eq : <some_number> } } "part, how do I add such conditions in my
Operation
?The text was updated successfully, but these errors were encountered: