i have these two assets :
1]
asset bloodBankInformations identified by bloodBankId {
o String bloodBankId
o contact bloodBankContactDetails
--> bloodData bloodBankBloodData
}
2]
asset bloodData extends bloodBankInformations {
o String bloodDatakey
o bloodquotas bloodquota
}
now i want to query on this asset such that i can get data from both assets in one single query.
Composer Queries are run against a single Asset or Participant registry. There is no 'join' as you might see in a relational database.
However for your example it is possible to use a Filter on the REST server to filter the results (like a Query) and resolve the relationship of relationship fields.
Before showing you my example I wonder if you really wanted to 'extend' original asset? So I have simplified your model in my example - but the same principle works if you did intend to extend.
Model:
asset bloodBankInformations identified by bloodBankId {
o String bloodBankId
o contact bloodBankContactDetails
--> bloodData bloodBankBloodData
}
asset bloodData extends bloodBankInformations {
o String bloodDatakey
o bloodquotas bloodquota
}
Filter:
On the REST server used on GET on the endpoint /blookBankInformations
{"where":{"bloodBankId":"BB03"},"include":"resolve"}
My Response Body:
[
{
"$class": "org.acme.mynetwork.bloodBankInformations",
"bloodBankId": "BB03",
"bloodBankContactDetails": "Diferent address!",
"bloodBankBloodData": {
"$class": "org.acme.mynetwork.bloodData",
"bloodDatakey": "BL04",
"bloodquota": "Quota BBBB"
}
}
]
There is some additional information in the Composer Knowledge Wiki on filters.
Related
In my hyperledger composer project I have a medicine as an asset. There are different types of medicine, but all medicine need to be approved before they are allowed to be produced and distributed in the supply chain.
Can I store a list of allowed assets in the blockchain, a list which can grow or shrink? Or do I have to store it off-chain?
edit: grammar mistake fixed.
Based on your reply to Riccardo Bonesi, I suggest something like this
asset AllowedMedicines identified by id {
o String id
o Medicines[] medicines
}
concept Medicines {
o String medicineId
o String medicineName
o Participants[] allowedParticipants
}
concept Participants {
o String participantId // either this is one below
--> Participant somePerson
// Any specific meta data you want to store
}
Now in your .js files you can do something like this
const allowedMedicines = await registry.get(id);
const participant; // The person you are checking for
const medicineId; // The medicine against which you are checking
const medicines = allowedMedicines.medicines;
if (medicines.medicineId.contains(medicineId)) {
// Medicine is in the list;
let allowedParticipants = medicines.allowedParticipants;
if (allowedParticipants.contains(participant) {
// The participant is allowed access to the medicine
};
};
Now of course based on the composer version, some syntax may need to be tweaked, but is the general idea of how you can maintain a mapping.
1.i want to know whether i can make changes to the parmeter defined in the relationship.
what i want to do is to make a function with name of bookflight and then make changes to the number of seats if the flight is booked .
these are my cto files
namespace org.acme.airline.aircraft
/** Aircraft is an ACME Asset*/
asset Aircraft identified by aircraftId {
o String aircraftId
o Ownership ownershipType default="LEASED"
// Number of seats per class
o Integer firstClassSeats range = [4,]
o Integer businessClassSeats range = [6, 20]
o Integer economyClassSeats range = [30, ]
o String nickName optional
}
enum Ownership {
o LEASED
o OWNED
}
and for flight the code is
namespace org.acme.airline.flight
import org.acme.airline.aircraft.Aircraft
asset Flight identified by flightId {
// Solution to the exercise - try out the Regular expression at http://regex101.com
// Share your optimized regular expression with others :)
o String flightId regex=/[A-Z][A-Z][0-9][0-9][0-9]-[0-9][0-9]-[0-3][0-9]-[0-9][0-9]/
o String flightNumber
o Route route
o String[] aliasFlightNumber optional
--> Aircraft aircraft optional
}
concept Route {
o String origin regex=/[A-Z][A-Z][A-Z]/
o String destination regex=/[A-Z][A-Z][A-Z]/
o DateTime schedule
}
// Logistics department of ACME creates the flights
transaction CreateFlight {
o String flightNumber
o String origin
o String destination
o DateTime schedule
}
event FlightCreated {
o String flightId
}
// Assigns an aircraft to the flight
// The logistics / validation on availability of aircraft
// Kept outside of the Blockchain
transaction AssignAircraft {
o String flightId
o String aircraftId
}
// Event indicating that aircraft was assigned
event AircraftAssigned {
o String flightId
o String aircraftId
}
now what i want to make changes to reltionship in the flight
to make changes to it what should i do . i have made a javascript file.to
access make changes in it.
function booktickets(registry){
//array to recored the hold the instances of aircraft resourse
const bnDef = bnUtil.connection.getBusinessNetwork();
const factory = bnDef.getFactory();
let flightResource = factory.newResource(aircraftNamespace,aircraftType,'AE201-05-05-2020');
flightResource.setPropertyValue('flightNumber','AE101');
flightResource.route = factory.newConcept(aircraftNamespace,'Route');
flightResource.route.setPropertyValue('origin', 'DEL');
flightResource.route.setPropertyValue('destination' , 'APH');
flightResource.route.setPropertyValue('schedule' , new Date('2018-10-15T21:44Z'));
flightResource.aircraft = factory.newRelationship('org.acme.airline.aircraft', 'Aircraft', 'CRAFT01');
//.setPropertyValue()
flightResource.aircraft.setPropertyValue('ownershipType','LEASED');
flightResource.aircraft.setPropertyValue('firstClassSeats',10);
flightResource.aircraft.setPropertyValue('businessClassSeats',10);
flightResource.aircraft.setPropertyValue('economyClassSeats',100);
return registry.update(flightResource).then(()=>{
console.log('Successfully created the flight!!!');
bnUtil.disconnect();
}).catch((error)=>{
console.log(error);
bnUtil.disconnect();
});
}
your question appears to be: can you create a relationship from Flight (asset) to Aircraft (asset) in a transaction function (that operates in the chaincode runtime), and can you update the fields of the related Aircraft (in its separate registry). The answer is 'yes', you can, for both. You don't provide the model for the bookflight function, so can only make assumptions about its model definition. as a minimum (based on your code) it will need:
transaction bookflight { }
A code example of what you are trying to do with relationships - is shown here -> https://github.com/hyperledger/composer-sample-networks/blob/master/packages/perishable-network/lib/logic.js#L130
This section:
const bnDef = bnUtil.connection.getBusinessNetwork();
const factory = bnDef.getFactory();
is composer-client code - and will not work inside a transaction function (that is runtime code, you need to remove client code - the example below shows 'how' to do it.) Replace line 2 with :
const factory = getFactory();
See more on transaction functions, examples etc at https://hyperledger.github.io/composer/latest/reference/js_scripts
note: you can just assign values like:
flightResource.route.origin = 'DEL' ; // no need for.setPropertyValue('origin', 'DEL'); etc etc
I don't see your code to update the Aircraft registry (with flightResource.aircraft FYI) - but you would need that to update the fields in that related asset (presently, you're only updating the Flight registry above )
new Date() is non deterministic code - if you're hoping to achieve consensus from multiple peers/orgs.
You'll notice the link I sent earlier, shows the use of async/await rather than JS promises (.then etc etc) - easier to code, easier to read. cheers.
I would like to create a query which returns all the Requests (asset) in which the Container's (asset) owner's id is equal to the parameter.
Model file (owner of a container is a Company participant, identified by id):
namespace org.acme.shipping.assets
import org.acme.shipping.participants.*
asset Container identified by number {
o String number
o ContainerType type
o String content
o ContainerStatus status default = "FREE"
--> Company owner
}
enum ContainerType {
o DRY
o REEFER
}
enum ContainerStatus {
o LOCKED
o FREE
}
asset Request identified by id {
o String id
--> Container container
}
Query file
query getRequestsByCompany {
description: "Get requests by company"
statement:
SELECT org.acme.shipping.assets.Request
WHERE (container.owner.id == _$company_id)
}
However, the current query does not seem to work. Is this achievable with a query?
I did a lot of research also to do it using query file, but couldnt find a way, so I think that its not possible at moment.
The alternative way is to use loopback filters:
https://github.com/hyperledger/composer-knowledge-wiki/blob/latest/knowledge.md#information_source--filters-loopback
https://loopback.io/doc/en/lb2/Where-filter.html
Something like:
{"where":{"shipmentId":1000}, "include":"resolve"}
you can go one level in like search by number . I am working on it if get the exact solution .
query getRequestsByCompany {
description: "Get requests by company"
statement:
SELECT org.acme.shipping.assets.Request
WHERE (container == _$container)
}
Using Grails (or hibernate), I was wanting to know if there is a specific design pattern or method we should be using when implementing a SEARCH of our domain.
For example, on my website, I want to be able to filter(or search) by multiple properties in the domain.
EG: For I have a page which displays a list of HOTELS. When I submit a search form, or if a user clicks "filter by name='blah'", when I enter the controller I get the following:
Domain
String name
String location
Controller
if(params.name && params.reference) {
// Find name/reference
} else if(params.name) {
// Find name
} else if(params.reference) {
// Find reference
} else {
// Find all
}
As you can understand, if there are more properties in the domain to search/filter, the longer the controller gets.
Any help. Please note, I do not want to use the 'searchable' plugin, as this is too complex for my needs.
I would embed these in a named query in the Domain class itself. For example:
Class Hotel {
String name
String city
String country
boolean isNice
static namedQueries = {
customSearch { p ->
if (p?.name) eq('name', p.name)
if (p?.city) eq('name', p.city)
if (p?.country) eq('name', p.country)
if (p?.isNice != null) eq('isNice', p.isNice)
}
}
}
Then later in a controller somewhere ...
def results = Hotel.customSearch(params)
Of course this is a very simple example, but you can expand on it using the same named query or even adding others and chaining them together.
Im working on rebuilding a clients software and they want to keep their database as unmodified as possible.
I got a table where they collect users and orders for different companies, no biggie there but the twist is they do it for multiple entities.
for example the table looks like this:
ID
UserID
Index
CompanyID
Type
lets say they got entities like Project and Workflow, then the Type column would be 'P' for projects and 'W' for workflows. So on a ID is the ID of a Project or Workflow Identity. UserID is always a foreign key to a User entity and Index is the order that the user is used when this Project/Workflow is used. And CompanyID is what company owns project or workflow entity.
I have tried to search google for this but i came up with nothing.
What i want is on a Template entity map two collections say StandardProjectUsers and StandardWorkflowUsers and they should collect them from correct entities with a user and index for current company.
Is this at all possible with fluent nhibernate ?
A nice article on how to do it: http://www.philliphaydon.com/2011/08/fluent-nhibernate-table-inheritance-discriminators/
You are looking at a table-per-hierarchy strategy.
In a nutshell you use:
public class BaseClassMap : ClassMap<BaseClass>
{
public BaseClassMap()
{
DiscriminateSubClassesOnColumn("Type");
...
}
}
public class WorkflowMap : SubclassMap<Workflow>
{
public WorkflowMap()
{
DiscriminatorValue("W");
...
}
}
public class ProjectMap : SubclassMap<Project>
{
public ProjectMap()
{
DiscriminatorValue("P");
...
}
}