Querying in Hyperledger Composer - hyperledger

When I try to make the query:
query PapersFromAPoll
{
description: "retrieve all the papers from a poll"
statement:
SELECT org.acme.democracity.Paper
WHERE(poll.pollId == _$id)
}
I am not able to get any rows, here is the fragment where I make this query:
return query('PapersFromAPoll',{id : count.poll.pollId})
It is strange because when I erase the WHERE statement and I make a simple query without any parameters it works perfectly.
Paper and Poll in model.cto file:
asset Paper identified by paperId {
o String paperId
o String[] fields
--> Poll poll //Paper related with a poll
}
asset Poll identified by pollId {
o String pollId
o Ask[] asks
}

query PapersFromAPoll
{
description: "retrieve all the papers from a poll"
statement:
SELECT org.acme.democracity.Paper
WHERE(poll == _$pollId)
}
So you can filter by the Poll asset by giving a reference to that Poll asset. When you try to query with the pollId it will have to be a reference to the resource resource:org.acme.democracity.Poll#{insert_id}

Related

How is hyperledger composer playground implementing the "All Transactions"?

When I try to use a query for "org.hyperledger.composer.system.HistorianRecord" the results doesn't show the input for system transactions like AddAsset, AddParticipant, etc.
I want to create an audit trail for a single asset using queries.
There have been many questions about tracking the history of the asset, but I couldn't find a solution for this.
There must be a solution to this, hyperledger playground shows exactly how I would prefer in its "All Transaction" in the test section. So how can we code something to get same output as all transactions.
the query i used
query selectHistoricalRecord {
description: "Select all Historical Record of AddAsset"
statement:
SELECT org.hyperledger.composer.system.HistorianRecord
WHERE (transactionType == 'org.hyperledger.composer.system.AddAsset')
}
the logic.js for this
/**
* Remove all high volume commodities
* #param {org.example.trading.GetAssetHistory} tx - the asset for constructing audit trail
* #transaction
*/
async function GetAssetHistory(tx)
{
let results = await query('selectHistoricalRecord');
console.log( results );
}
the output is as:
but in all transaction:
we get something like this:
My questions is how is this "all transactions" showing the input, but historian doesn't. What other way can i get input for system transactions.
This query should get you the results:
query a2 {
description: "Select Transaction"
statement:
SELECT org.hyperledger.composer.system.AddAsset
}

Querying over nested assets in Hyperledger Composer

I want to write a specific query for my Hyperledger Composer app. Below, I have 2 assets and a transaction. Asset1 has a field called contents, which is an array of type Asset2. The associated code is below:
namespace org.acme.biznet
asset Asset1 identified by Asset1Id {
o String Asset1Id
--> Asset2[] contents
}
asset Asset2 identified by Asset2Id {
o String Asset2Id
}
transaction Transact {
--> Asset1 asset1
}
I want to select all instances of Transact where the associated Asset1 has a specified Asset2 inside. The closest solution I came to the query below, which did not work.
query GetTransactionsThatHaveAsset2 {
description: ""
statement:
SELECT org.acme.biznet.Transact
WHERE (asset1.contents CONTAINS (Asset2Id == _$propId))
}
The thing is, I have also written the query below.
query GetAsset1sThatHaveAsset2 {
description: ""
statement:
SELECT org.acme.biznet.Asset1
WHERE (contents CONTAINS (Asset2Id == _$propId))
}
This query behaves as intended, but it's selecting over Asset1. I want to select over Transact. How would I write this query?
no, you can't presently nest the query like you propose, nested named queries are not currently implemented in Composer (CouchDB is not a relational DB, and hence Composer query language can't translate the nested query presently to be translated to CouchDB) 2) Transact is a transaction - it contains a relationship identifier(s) you defined in your model, not the nested data stored in the related asset. You would have to define a query that searches for all transactions that matches the asset1 identifier field you passed to the trxn - then in your code, you can check transact.asset1.contents contains the 'something' (passed in to the trxn too?) using a javascript match - quite straightforward). Alternatively, you could use the REST API filters (loopback filters as opposed to queries) where (form your app code) you can resolve the relationships of transaction (Transact) back to asset1 (and its contents) using the REST call with filter eg
{"where":{"asset1":"resource:org.acme.net.Asset1#1"}, "include":"resolve"} . Hope this helps, maybe its nesting you're looking for exclusively..
In my case, I have these assets
// Define assets
asset Product identified by productId {
o String productId
o String description
o String serialNumber
o String modelNumber
o String status // TRANSFERED, RECEIVED, RECLAMED
o DateTime joinTime
--> Trader previousOwner
--> Trader currentOwner
--> Trader newOwner
}
// Trade, moves product from to a new owner.
transaction Trade {
--> Product product
--> Trader newOwner
o String trade_type
}
Executing a trade transaction results in the record:
{
"$class": "org.sp.network.Trade",
"product": "resource:org.sp.network.Product#123",
"newOwner": "resource:org.sp.network.Trader#6694",
"trade_type": "Trade",
"transactionId": "e39a86ed4748a3ab73b5e9c023f6bb0ca025098af09b8b5b2dca8f5f7ef0db67",
"timestamp": "2019-06-13T12:04:20.180Z"
}
And to query all Trade transactions that contain a product is
query ProductPath{
description: "Selete all Trade transactions for a specific ProductId"
statement:
SELECT org.sp.network.Trade
WHERE (_$productId==product)
}
Using the rest server: the value of _$productId is resource:org.sp.network.Product#123

Neo4j+PopotoJS: filter graph based-on predefined constraints

I have a question about the query based on the predefined constraints in PopotoJs. In this example, the graph can be filtered based on the constraints defined in the search boxes. The sample file in this example visualizations folder, constraint is only defined for "Person" node. It is specified in the sample html file like the following:
"Person": {
"returnAttributes": ["name", "born"],
"constraintAttribute": "name",
// Return a predefined constraint that can be edited in the page.
"getPredefinedConstraints": function (node) {
return personPredefinedConstraints;
},
....
In my graph I would like to apply that query function for more than one node. For example I have 2 nodes: Contact (has "name" attribute) and Delivery (has "address" attribute)
I succeeded it by defining two functions for each nodes. However, I also had to put two search box forms with different input id (like constraint1 and constraint2). And I had to make the queries in the associated search boxes.
Is there a way to make queries which are defined for multiple nodes in one search box? For example searching Contact-name and/or Delivery-adress in the same search box?
Thanks
First I’d like to specify that the predefined constraints feature is still experimental (but fully functional) and doesn’t have any documentation yet.
It is intended to be used in configuration to filter data displayed in nodes and in the example the use of search boxes is just to show dynamically how it works.
A common use of this feature would be to add the list of predefined constraint you want in the configuration for every node types.
Let's take an example:
With the following configuration example the graph will be filtered to show only Person nodes having "born" attribute and only Movie nodes with title in the provided list:
"Person": {
"getPredefinedConstraints": function (node) {
return ["has($identifier.born)"];
},
...
}
"Movie": {
"getPredefinedConstraints": function (node) {
return ["$identifier.title IN [\"The Matrix\", \"The Matrix Reloaded\", \"The Matrix Revolutions\"]"];
},
...
}
The $identifier variable is then replaced during query generation with the corresponding node identifier. In this case the generated query would look like this:
MATCH (person:`Person`) WHERE has(person.born) RETURN person
In your case if I understood your question correctly you are trying to use this feature to implement a search box to filter the data. I'm still working on that feature but it won't be available soon :(
This is a workaround but maybe it could work in your use case, you could keep the search box value in a variable:
var value = d3.select("#constraint")[0][0].value;
inputValue = value;
Then use it in the predefined constraint of all the nodes type you want.
In this example Person will be filtered based on the name attribute and Movie on title:
"Person": {
"getPredefinedConstraints": function (node) {
if (inputValue) {
return ["$identifier.name =~ '(?i).*" + inputValue + ".*'"];
} else {
return [];
}
},
...
}
"Movie": {
"getPredefinedConstraints": function (node) {
if (inputValue) {
return ["$identifier.title =~ '(?i).*" + inputValue + ".*'"];
} else {
return [];
}
},
...
}
Everything is in the HTML page of this example so you can view the full source directly on the page.
#Popoto, thanks for the descriptive reply. I tried your suggestion and it worked pretty much well. With the actual codes, when I make a query it was showing only the queried node and make the other node amount zero. I wanted to make a query which queries only the related node while the number of other nodes are still same.
I tried a temporary solution for my problem. What I did is:
Export the all the node data to JSON file, search my query constraint in the exported JSONs, if the file is existing in JSON, then run the query in the related node; and if not, do nothing.
With that way, of course I needed to define many functions with different variable names (as much as the node amount). Anyhow, it is not a propoer way, bu it worked for now.

Groovy name queried

I got a domain like this:
ZZPartAndTeam
String parts
String team
Parts may have many team.
For ex: part:part1 team:10
part:part1 team:20
part:part2 team:30
How can I query in the domain that get all parts which have multi team?
result:part:part1 team:10
part:part1 team:20
Thanks.
The HAVING clause is not supported by Hibernate Criteria. A way around is to use DetachedCriteria.
import org.hibernate.criterion.DetachedCriteria as HDetachedCriteria
query: { builder, params ->
// This query counts the number of teams per part
HDetachedCriteria innerQry = HDetachedCriteria.forClass(ZZPartAndTeam.class)
innerQry.setProjection(Projections.projectionList()
.add(Projections.count('team').as('teamCount'))
)
innerQry.add(HRestrictions.eqProperty('part', 'outer.part')
// Using innerQuery, this criteria returns the parts having more than one team.
HDetachedCriteria outerQry = HDetachedCriteria.forClass(ZZPartAndTeam.class, 'outer')
outerQry.setProjection(Projections.projectionList()
.add(Projections.distinct(Projections.property('part').as('part')))
)
outerQry.add(Subqueries.gt(1, innerQry))
builder.addToCriteria(Property.forName('part').in(outerQry))
}

StackOverflowException caused by a linq query

edit #2: Question solved halfways. Look below
As a follow-up question, does anyone know of a non-intrusive way to solve what i'm trying to do below (namely, linking objects to each other without triggering infinite loops)?
I try to create a asp.net-mvc web application, and get a StackOverFlowException. A controller triggers the following command:
public ActionResult ShowCountry(int id)
{
Country country = _gameService.GetCountry(id);
return View(country);
}
The GameService handles it like this (WithCountryId is an extension):
public Country GetCountry(int id)
{
return _gameRepository.GetCountries().WithCountryId(id).SingleOrDefault();
}
The GameRepository handles it like this:
public IQueryable<Country> GetCountries()
{
var countries = from c in _db.Countries
select new Country
{
Id = c.Id,
Name = c.Name,
ShortDescription = c.ShortDescription,
FlagImage = c.FlagImage,
Game = GetGames().Where(g => g.Id == c.GameId).SingleOrDefault(),
SubRegion = GetSubRegions().Where(sr => sr.Id == c.SubRegionId).SingleOrDefault(),
};
return countries;
}
The GetGames() method causes the StackOverflowException:
public IQueryable<Game> GetGames()
{
var games = from g in _db.Games
select new Game
{
Id = g.Id,
Name = g.Name
};
return games;
}
My Business objects are different from the linq2sql classes, that's why I fill them with a select new.
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
edit #1: I have found the culprit, it's the following method, it triggers the GetCountries() method which in return triggers the GetSubRegions() again, ad nauseam:
public IQueryable<SubRegion> GetSubRegions()
{
return from sr in _db.SubRegions
select new SubRegion
{
Id = sr.Id,
Name = sr.Name,
ShortDescription = sr.ShortDescription,
Game = GetGames().Where(g => g.Id == sr.GameId).SingleOrDefault(),
Region = GetRegions().Where(r => r.Id == sr.RegionId).SingleOrDefault(),
Countries = new LazyList<Country>(GetCountries().Where(c => c.SubRegion.Id == sr.Id))
};
}
Might have to think of something else here :) That's what happens when you think in an OO mindset because of too much coffee
Hai! I think your models are recursively calling a method unintentionally, which results in the stack overflow. Like, for instance, your Subregion object is trying to get Country objects, which in turn have to get Subregions.
Anyhow, it always helps to check the stack in a StackOverflow exception. If you see a property being accessed over and over, its most likely because you're doing something like this:
public object MyProperty { set { MyProperty = value; }}
Its easier to spot situations like yours, where method A calls method B which calls method A, because you can see the same methods showing up two or more times in the call stack.
The problem might be this: countries have subregions and subregions have countries. I don't know how you implement the lazy list, but that might keep calling GetCountries and then GetSubRegions and so on. To find that out, I would launch the debugger en set breakpoints on the GetCountries and GetSubRegions method headers.
I tried similar patterns with LinqToSql, but it's hard to make bidirectional navigation work without affecting the performance to much. That's one of the reasons I'm using NHibernate right now.
To answer your edited question, namely: "linking objects to each other without triggering infinite loops":
Assuming you've got some sort of relation where both sides need to know about the other... get hold of all the relevant entities in both sides, then link them together, rather than trying to make the fetch of one side automatically fetch the other. Or just make one side fetch the other, and then fix up the remaining one. So in your case, the options would be:
Option 1:
Fetch all countries (leaving Subregions blank)
Fetch all Subregions (leaving Countries blank)
For each Subregion, look through the list of Countries and add the Subregion to the Country and the Country to the Subregion
Option 2:
Fetch all countries (leaving Subregions blank)
Fetch all Subregions, setting Subregion.Countries via the countries list fetched above
For each subregion, go through all its countries and add it to that country
(Or reverse country and subregion)
They're basically equialent answers, it just changes when you do some of the linking.

Resources