Graphene/GraphQL find specific column value - django

For some reason, I can't figure out how to simply find a specific piece of data in my SQLAlchemy database.
In the graphene-python documentation it simply does this query to match the id (which is a string):
book(id: "Qm9vazow") {
id
title
}
Now here's my Flask-Graphene-SQLAlchemy code for my BookSchema and I want to find a specific title instead of an ID:
class BookModel(db.Model):
__table__ = db.Model.metadata.tables['books_book']
# Schema Object
class BookSchema(SQLAlchemyObjectType):
class Meta:
model = BookModel
interfaces = (relay.Node, )
# Connection
class BookConnection(relay.Connection):
class Meta:
node = BookSchema
# GraphQL query
class Query(graphene.ObjectType):
node = relay.Node.Field()
allBooks = SQLAlchemyConnectionField(BookConnection)
schema = graphene.Schema(query=Query, types=[BookSchema])
When I run this query, everything is fine and returns 3 book titles:
{
"query": "{ allBooks(first: 3) { edges { node { title } } } }"
}
However, once I try to match a specific title, it stops working. For example:
# I tried all these queries, none worked
1. { allBooks(title: \"some book title\") { edges { node { title } } } }
2. { allBooks(title: \"some book title\") { title }
3. { allBooks(title: 'some book title') { edges { node { title } } } }
The error: "Unknown argument \"title\" on field \"allBooks\" of type \"Query\"."
I must be making a small error that I'm not seeing, but I can't figure it out. I've spent hours trying to figure this out.
Question: How can I match the title and have it return the object? What am I doing wrong?

Figured it out! See changes below.
class Query(graphene.ObjectType):
node = relay.Node.Field()
all_books = SQLAlchemyConnectionField(BookConnection)
# Added this
find_book = graphene.Field(BookSchema, title = graphene.String())
def resolve_find_book(self, info, title):
query = BookSchema.get_query(info)
return query.filter(BookModel.title == title).first()
And my GraphQL query looks like this:
{
"query": "{ findBook(title: \"some book title\") { title } }"
}
Hope this helps someone in the future!

Related

Access feature importance from trained Vertex AI Tabular regression model using Python

I am working with models trained using the Tabular automl of Vertex in GCP.
Training and batch predictions work fine. I am trying to use the feature importance in visualizations and trying to get to them from within python.
I can get to the model evaluations with the code #Ricco D posted for me:
api_endpoint = 'us-central1-aiplatform.googleapis.com'
client_options = {"api_endpoint": api_endpoint} # api_endpoint is required for client_options
client_model = aiplatform.services.model_service.ModelServiceClient(client_options=client_options)
project_id = 't...1'
location = 'us-central1'
model_id = '6...2'
model_name = f'projects/{project_id}/locations/{location}/models/{model_id}'
list_eval_request = aiplatform.types.ListModelEvaluationsRequest(parent=model_name)
list_eval = client_model.list_model_evaluations(request=list_eval_request)
for val in list_eval:
print(val.model_explanation)
But I can not figure out how to get the trained model's feature importance's that were generated in the training pipeline. I can see them on the model page but can't access them from python:
The code returned ListModelEvaluationsPager object is this:
name: "projects/7...3/locations/us-central1/models/6...2/evaluations/5...0"
metrics_schema_uri: "gs://google-cloud-aiplatform/schema/modelevaluation/regression_metrics_1.0.0.yaml"
metrics {
struct_value {
fields {
key: "meanAbsoluteError"
value {
number_value: 27.391115
}
}
fields {
key: "meanAbsolutePercentageError"
value {
number_value: 25.082605
}
}
fields {
key: "rSquared"
value {
number_value: 0.88434035
}
}
fields {
key: "rootMeanSquaredError"
value {
number_value: 47.997845
}
}
fields {
key: "rootMeanSquaredLogError"
value {
number_value: nan
}
}
}
}
create_time {
seconds: 1630550819
nanos: 842478000
}
}
>```
This object does not have a model_explanation member and the code returns an error
A working solution with code was posted to answer this by Ricco D here Correct answer by Ricco D
Feature attributions are included in Vertex AI predictions through Vertex Explainable AI.
For batch predictions, you need to set generate_explanation to True in your python BatchPredictionJob class like in this example from the documentation:
Note that Feature importance is not supported when the prediction data is returned in Cloud Storage or for forecasting models.
batch_prediction_job = {
"display_name": display_name,
# Format: 'projects/{project}/locations/{location}/models/{model_id}'
"model": model_name,
"model_parameters": model_parameters,
"input_config": {
"instances_format": instances_format,
"bigquery_source": {"input_uri": bigquery_source_input_uri},
},
"output_config": {
"predictions_format": predictions_format,
"bigquery_destination": {"output_uri": bigquery_destination_output_uri},
},
# optional
"generate_explanation": True,

Model of a nested document in pymodm or mongoengine to work in Django

I have a specific kind of JSON which I need to code into a model for my Django problem. Problem is I have nested document in it or should I say object of objects and I don't know how to design the model in Pymodm or Mongoengine.
Here is the JSON schema on which I am working.
{
"something": "something",
"safasf": 5,
"key": {
"value1": ["dsd", "dd"],
"value2": {
"blah1": "blahvalue1",
"blah2": "blahvalue2"
}
}
}
I have already looked into the documentation and API References of both these ODMs. I could not find anything useful. At best they have fields.EmbeddedDocumentListField which stores list of documents/objects.
Your sample json is quite meaningless but this is an example of how you could model it with mongoengine
from mongoengine import *
class MyNestedDoc(EmbeddedDocument):
value1 = ListField(StringField())
value2 = DictField(StringField())
class MyDocument(Document):
something = StringField()
safasf = IntField()
key = EmbeddedDocumentField(MyNestedDoc)
nested_doc = MyNestedDoc(
value1=["dsd", "dd"],
value2={
"blah1": "blahvalue1",
"blah2": "blahvalue2"
}
)
doc = MyDocument(something="something", safasf=5, key=nested_doc)
doc.save()
This will save in Mongo an object with the following shape
{'_id': ObjectId('5d2d832c96d2914c2a32c1b3'),
'key': {
'value1': ['dsd', 'dd'],
'value2': {
'blah1': 'blahvalue1',
'blah2': 'blahvalue2'
}
},
'safasf': 5,
'something': 'something'
}

Unknown field `edges` on type `Query`

I am getting the error from the title when I attempt to run relay-compiler in my project. I am using graphql-python/graphene-django for the back end graphql server. Here's an abbreviated copy of my schema.
grove.gql_schema.py:
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
from .models import Tree
class TreeNode(DjangoObjectType):
class Meta:
model = Tree
filter_fields = ['owner']
interfaces = (relay.Node,)
class Query(ObjectType):
def resolve_my_trees(self, info):
if not info.context.user.is_authenticated:
return Tree.objects.none()
else:
return Tree.objects.filter(owner=info.context.user)
my_trees = DjangoFilterConnectionField(TreeNode)
tree = relay.Node.Field(TreeNode)
project.gql_schema:
class Query(grove.gql_schema.Query, graphene.ObjectType):
pass
schema = graphene.Schema(query=Query)
With that setup, I can successfully run the following query in GraphiQL
query {
myTrees {
edges {
node {
id
}
}
}
}
So far so good, but now I'm trying to build a client-side component that can use this query.
jsapp/components/index.jsx:
import React from 'react';
import {graphql, QueryRenderer} from 'react-relay';
import environment from '../relay_env'
const myTreesQuery = graphql`
query componentsMyTreesQuery {
edges {
node {
id
}
}
}
`;
export default class App extends React.Component {
render() {
return (
<QueryRenderer
environment={environment}
query={myTreesQuery}
variables={{}}
render={({error, props}) => {
if (error) {
return <div>Error!</div>;
}
if (!props) {
return <div>Loading...</div>;
}
return <div>User ID: {props.edges}</div>;
}}
/>
);
}
}
The query is identical, but when I run relay-compiler --src ./jsapp --schema ./schema.graphql --extensions js jsx I get the error:
GraphQLParser: Unknown field `edges` on type `Query`.
Source: document `componentsMyTreesQuery` file: `components/index.jsx`.
I get this error if when I use the .json schema generated by the Django graphaql_schema management command or the .graphql one retrieved by get-graphql-schema.
What part am I missing?
I might be a bit late but it looks to me like you're trying to ask for the edges on the root of your schema, the fragment:
const myTreesQuery = graphql`
query componentsMyTreesQuery {
edges {
node {
id
}
}
}
`;
I think could be altered to:
const myTreesQuery = graphql`
query componentsMyTreesQuery {
myTrees {
edges {
node {
id
}
}
}
}
`;
The text after the keyword query refers to the name of the 'query', not the root of the schema. If you're using Relay Modern (which by the use of QueryRenderer, I assume you are) then the compiler should yell at you to fix the name of your fragment to something that reflects the filename that it's stored in.

Acumatica refer custom field to another custom field on different screen

I have created 2 custom fields(UsrFFA and UsrFreeFreightDay) as below in the Customers Screen.Customers Screen
Then I created similar fields on the Sales Order Screen as below
Sales Order
I want these fields on Sales Order screen to populate values for respective Customer ID.
I went through the training material T200 and found this code
protected void SOOrder_CustomerID_FieldUpdated(PXCache sender,PXFieldUpdatedEventArgs e)
{
SOOrder order = e.Row as SOOrder;
BAccount customer =
PXSelectorAttribute.Select<SOOrder.customerID>(sender, order)
as BAccount;
if (customer != null)
{
Contact defContact = PXSelect<Contact,
Where<Contact.bAccountID, Equal<Required<Contact.bAccountID>>,
And<Contact.contactID, Equal<Required<Contact.contactID>>>>>
.Select(Base, customer.BAccountID, customer.DefContactID);
if (defContact != null)
{
ContactExt contactExt = PXCache<Contact>
.GetExtension<ContactExt>(defContact);
sender.SetValue<SOOrderExt.usrCRVerified>(order,
contactExt.UsrCreditRecordVerified);
}
}
}
I am not able to understand this code and how should I use it in my customization.
You should subscribe to FieldUpdated handler for the SOOrder.CustomerID field and populate your custom fields on the Sales Order screen in the same way as shown in Example 5.2: Inserting a Default Detail Data Record of the T200 training class:
protected virtual void ShipmentLine_ProductID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
// Obtain the new data record that contains the updated
// values of all data fields
ShipmentLine line = (ShipmentLine)e.Row;
line.Description = string.Empty;
if (line.ProductID != null)
{
Product product = PXSelectorAttribute.Select<ShipmentLine.productID>(sender, line) as Product;
if (product != null)
{
// Copy the product name to the description of the shipment line
line.Description = product.ProductName;
}
}
}
You might also check Step 3.1: Adding the FieldUpdated Event Handler (CustomerMaint) and Step 5.2: Customizing Business Logic for the Sales Orders form (SOOrderEntry) from the T300 training class for additional samples.
The code snippet below should accomplish desired results on the Sales Orders screen. If you still have issues understanding the code below, I highly recommend you to go through the T300 training class for very detailed hands-on exercises with step-by-step instructions.
public class SOOrderEntryExt : PXGraphExtension<SOOrderEntry>
{
public void SOOrder_CustomerID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
var order = e.Row as SOOrder;
if (order.CustomerID != null)
{
var customer = PXSelectorAttribute.Select<SOOrder.customerID>(sender, order) as BAccountR;
if (customer != null)
{
var customerExt = customer.GetExtension<BAccountExt>();
var orderExt = order.GetExtension<SOOrderExt>();
orderExt.UsrFFA = customerExt.UsrFFA;
orderExt.UsrFreeFreightDay = customerExt.UsrFreeFreightDay;
}
}
}
}
Customize the attributes on the SOOrder field in the following way:
For UsrFFA field
[PXDBString(100)]
[PXUIField(DisplayName="FFA", Visible = true, Enabled = false)]
[PXFormula(typeof(Selector<SOOrder.customerID, BAccountExt.usrFFA>))]
For UsrFreeFreightDay field
[PXDBString(100)]
[PXUIField(DisplayName="Free Freight Day", Visible = true, Enabled = false)]
[PXFormula(typeof(Selector<SOOrder.customerID, BAccountExt.usrFreeFreightDay>))]

How do I bind XPath expression values to a template using Groovy

I have a small Groovy Class called "zzz". The purpose of this class is to first demonstrate successfully passing a binding to the template engine producing an output and then failing to bind to another template engine using what appears to be the same set of bindings.
V1.template contains the base message that will be used with the bindings to produce a final output. V1.properties contains an XPath expression that should grab the value from an XML document and add it to the bindings. T1.xml is the raw xml input file.
In the zzz Groovy Class I have hard coded the LastName in bindings1 and that works. But, when I grab the lastName value from the XML file and add it to bindings2 it fails. Both bindings appear to have exactly the same text, but I have noticed that bindings1 is of type Bindings and binding2 is of type Reference.
I assume that bindings2 being of Reference is what is causing my problem, but I don't know how to cast or convert it to Binding. Please let me know what I'm doing wrong.
I'm using Java 1.8 with groovy-all-2.3.10.jar
zzz.groovy:
import java.io.File;
import javax.xml.xpath.*
import javax.xml.parsers.DocumentBuilderFactory
class zzz {
def xpath
def records
def loadDocToCheck(File docToCheck) {
xpath = XPathFactory.newInstance().newXPath()
def builder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
def inputStream = new FileInputStream( docToCheck )
records = builder.parse(inputStream).documentElement
}
def validateXpath(String xpathQuery ) {
def nodes = xpath.evaluate( xpathQuery, records, XPathConstants.NODESET )
nodes.collect { node -> node.textContent }
def nodeCount = 0
nodes.each { nodeCount++ }
nodeCount
}
def getXpath(String xpathQuery ) {
String retVal = ""
def nodes = xpath.evaluate( xpathQuery, records, XPathConstants.NODESET )
nodes.collect { node ->
retVal += node.getTextContent()
}
(retVal)
}
static main(args) {
def zzz = new zzz()
def testFile = new File("T1.xml")
zzz.loadDocToCheck(testFile)
def config = new ConfigSlurper().parse(new File("V1.properties").toURI().toURL())
String testFileNameOnly = testFile.getName()-testFile.getParent()
def bindings1 = [
"InputFile" : "$testFileNameOnly",
"LastName" : "Smith"
]
def templateFile1 = new File('V1.template')
println "templateFile1=${templateFile1.getAbsolutePath()}"
def engine1 = new groovy.text.GStringTemplateEngine()
def template1 = engine1.createTemplate(templateFile1).make(bindings1)
println template1.toString()
println "******************************"
def bindings2 = [:]
bindings2 << ["InputFile":"$testFileNameOnly"]
config.params.each { paramName, param ->
bindings2 << ["$paramName" : "${zzz.getXpath(param)}"]
}
println "bindings2=$bindings2"
def templateFile2 = new File('V1.template')
println "templateFile=${templateFile2.getAbsolutePath()}"
def engine2 = new groovy.text.GStringTemplateEngine()
def template2 = engine2.createTemplate(templateFile2).make(bindings2)
println template2.toString()
}
}
T1.xml:
<?xml version="1.0"?>
<MyRoot specVersion="3.03">
<employee>
<lastName>Smith</lastName>
<firstName>John</firstName>
</employee>
</MyRoot>
V1.template:
Input file: ${InputFile}
LastName: ${LastName}
V1.properties:
params {
LastName = '//MyRoot/employee/lastName/text()'
}
I found why the second template would could execute. The bindings must be in the form of Map, but I was passing in a GString as the key for the map. Note: "$parameterName" is a GString. After converting the key to a String the second template executed correctly.