Is there a way to query / access list of available transaction classes in hyperledger composer? - hyperledger-composer

Can we query the business network to show a list of transaction classes? and knowing transaction class name, can we query the required parameters to pass when invoking it?
Eg: BusinessNetworkA consist of 3 Transaction classes {TradeApples, BuyCar, RentHouse}
TradeApples requires price per kg as parameter
BuyCar requires Car VIN and price as parameters
Rent requires House Number and price as parameters

That can be easily done:
query getCupData {
description: "particular batch"
statement:
SELECT org.ibm.coffee.cupCoffee
WHERE (cupId == _$CupId )
}
Use TradeApple in place of cupCoffe and pricePerKg in place of cupId and _$CupId would be input variable and you can have any type of query between your variable.
PS: This should go in a separate file named queries.qry (Name is Important should be same)

Related

Group queries in GraphQL (not "group by")

in my app there are many entities which get exposed by GraphQL. All that entities get Resolvers and those have many methods (I think they are called "fields" in GraphQl). Since there is only one Query type allowed, I get an "endless" list of fields which belong to many different contexts, i.E.:
query {
newsRss (...)
newsCurrent (...)
userById(...)
weatherCurrent (...)
weatherForecast(...)
# ... many more
}
As you can see, there are still 3 different contexts here: news, users and weather. Now I can go on and prefix all fields ([contextName]FieldName), as I did in the example, but the list gets longer and longer.
Is there a way to "group" some of them together, if they relate to the same context? Like so, in case of the weather context:
query {
weather {
current(...)
forecast(...)
}
}
Thanks in advance!
If you want to group them together , you need to have a type which contain all fields under the same context . Take weather as an example , you need to have a type which contain currentWeather and forecastWeather field. Does this concept make sense to your application such that you can name it easily and users will not feel strange about it ? If yes , you can change the schema to achieve your purpose.
On the other hand, if all fields of the same context actually return the same type but they just filtering different things, you can consider to define arguments in the root query field to specify the condition that you want to filter , something like :
query {
weather(type:CURRENT){}
}
and
query {
weather(type:FORECAST){}
}
to query the current weather and forecast weather respectively.
So it is a question about how you design the schema.

Is there a way to compare each item to a aggreated value?

I'm new to graphQL and Hasura. I'm trying(in Hasura) to let me users provide custom aggregation (ideally in the form of a normal graphQL query) and have then each item the results compared against the aggreation.
Here's a example. Assume I have this schema:
USERTABLE:
userID
Name
Age
City
Country
Gender
HairColor
INCOMETABLE:
userID
Income
I created a relationship in hasura and I can query the data but my users want to do custom scoring of users' income level. For example, one user may want to query the data broken down by country and gender.
For the first example the result maybe:
{Country : Canada
{ gender : female
{ userID: 1,
Name: Nancy Smith,..
#data below is on aggregated results
rank: 1
%fromAverage: 35%
}...
Where I'm struggling is the data showing the users info relative to the aggregated data.
for Rank, I get the order by sorting but I'm not sure how to display the relative ranking and for the %fromAverage, I'm not sure how to do it at all.
Is there a way to do this in Hasura? I suspected that actions might be able to do this but I'm not sure.
You can use track a Postgres view. Your view would have as many fields as you'd like calculated in SQL and tracked as a separate "table" on your graphql api.
I am giving examples below based on a simplification where you have just table called contacts with just a single field called: id which is an auto-integer. I am just adding the id of the current contact to the avg(id) (a useless endeavor to be sure; just to illustrate...). Obviously you can customize the logic to your liking.
A simple implementation of a view would look like this (make sure to hit 'track this' in hasura:
CREATE OR REPLACE VIEW contact_with_custom AS
SELECT id, (SELECT AVG(ID) FROM contacts) + id as custom FROM contacts;
See Extend with views
Another option is to use a computed field. This is just a postgres function that takes a row as an argument and returns some data and it just adds a new field to your existing 'table' in the Graphql API that is the return value of said function. (you don't 'track this' function; once created in the SQL section of Hasura, you add it as a 'computed field' under 'Modify' for the relevant table) Important to note that this option does not allow you to filter by this computed function, whereas in a view, all fields are filterable.
In the same schema mentioned above, a function for a computed field would look like this:
CREATE OR REPLACE FUNCTION custom(contact contacts)
RETURNS Numeric AS $$
SELECT (SELECT AVG(ID) from contacts ) + contact.id
$$ LANGUAGE sql STABLE;
Then you select this function for your computed field, naming it whatever you'd like...
See Computed fields

schema design union vs flat properties

when I have a parent Object type that needs to point to a child Object type but that child Object's type can be of several types and only one can be chosen and populated. I see 2 options I can do with regard to graphql schema design.
option 1 - use union
type child1{......}
type child2{......}
union chooseOne = child1 | child2
type parent{
ref: chooseOne
}
option 2 use multiple props and have only one with data - the rest with nulls
type child1{......}
type child2{......}
type parent{
ref1: child1
ref2: child2
}
is there a 3rd option I am not thinking of? I am not that please with either. I feel like I am missing something... can anyone please comment? thanks! (edited)
am I missing a third possible option?
using an array
type Meeting{
.........(some properties)
recurrences : [Recurrence]
}
union Recurrence = Once | WeeklyRecurrence | MonthlyRecurrence | DailyRecurrence
Of course it looks like a relation ... and it is ... and gives you more possibilities.
all of them can have validFrom and validUntil times - you can filter out all historical entries automatically without manual disabling/removing
you can have AND combinations instead OR, for example 'every working day at 10.00, additionally at 15.00 on fridays'
you can process recurrence entries separately f.e. for notifications (having meeting id just fetch attendees from another relation)
But in fact maybe you don't need separate recurrence types at all, only one field/property (enumerated types) to know which fields are required for render/forms/resolver/mutations etc.
... all of them can use the same DB table, the same record structures in both cases (types mapped to enumed type field).
Update
I prefer 2nd option:
it's more readable/debuggable
it's easier to handle - if(ref1)...<Ref1Component data={ref1}/> ... passing union data object you don't have info about type!
unions sometimes leads to troubles like this

LINQ: Joining List<object> and dataset on a comma separated value field?

I am using C# and LINQ and trying to combine two sets of data. The first is a List of a specific type, lets call this Status (List) which is just a class with a bunch of properties one of which includes a comma separated value list of accounts. This is queried from the application database using a stored procedure so I have some flexability as to what is displayed here
For example:
class Status
{
...
public string Accounts {get; set;} (ie. "abcde, qwerty, asdfg")
public string Managers {get; set;}
...
}
The rest of the properties are irrelevant as this is the only field I am joining on.
The second "Accounts" data set is from a web service which I am calling to get a list of "Accounts" and the people associated with each account.
For example:
Account Manager SomeData MoreFields ...
------- ------------------- -------- ---------- ---
abcde Bob Marley Data MoreData ...
qwerty Fred Flinstone Data MoreData ...
So bascially I need to Create a list of Status objects with a CSV list of Manager(s) from the Accounts dataset in the Managers property of Status. Problem is I have no control over what is retruend in this dataset as it is a third party application. So I need to find some way to do this without modifying the "Accounts" data. Unless I do something in memory after getting the dataset from the web service.
I hope this makes sense and I thank you in advance!
What is this "dataset" of which you speak? I don't care where it come from -- I just care what kind of object it is in C#.
I'm going to assume that it's an ICollection, called "accounts"
Next, I'm going to assume that Managers is a CVS list much like Accounts.
Further, I'm only going to create one status object instead of a "list" of them, since you never say what separates one status from another.
var status = new Status();
status.Accounts = string.Join( ", ", from k in accounts select k.Account);
status.Managers = string.Join( ", ", from k in accounts select k.Manager);

With the use of Apex code, how can I select all ''OpportunityProducts' objects which are belongs to particular 'Opportunity Id'

I am way to customizing 'Sales' application that belongs to 'salesforce.com' platform.
Is there any way to select all the 'OpportunityProducts' objects which are belongs to particular 'Opportunity Id' ?
[SELECT Id FROM OpportunityProduct WHERE Opportunity =:opportunitId];
When I execute above code for select those 'OpportunityProduct', I got following error. If any one have some idea please update me. Thanks.
Save error: sObject type 'OpportunityProduct' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name. Please reference your WSDL or the describe call for the appropriate names.
Another way to get this done when you need the actual products, not just the line items, is as follows. First get your opportunities:
List<Opportunity> opps = [SELECT Id, Name FROM Opportunity LIMIT 1000];
Then loop through to create a list of opportunity Ids
List<Id> oppIds = new List<Id>();
for(Opportunity o : opps)
{
oppIds.add(o.Id);
}
Now get your actual products that belong to your opportunities...
List<OpportunityLineItem> oppProds = [SELECT Id, PricebookEntry.Product2.Name, PricebookEntry.Product2.Family
FROM OpportunityLineItem
WHERE OpportunityId IN :oppIds];
Hope that helps.

Resources