I'm developing an application using Hyperledger composer and its related part of the model file as bellows.
abstract participant Stakeholder {
o String name
o Address address
o String email optional
o String telephone optional
o Certification certification optional
o String[] images optional
o Company company
o String username
o String password
}
participant Farmer identified by stakeholderId extends Stakeholder {
o String stakeholderId
o String description optional
--> Farm[] farms
}
I'm trying to retrieve specific farmers by their username using below query.
query getUserFromUsername{
description:"get user from username"
statement:
SELECT org.ucsc.agriblockchain.Stakeholder
WHERE (username == _$username)
}
But it does not work as expected. Here, since Farmer is not the only stakeholder in the system, the Stakeholder abstract participant is used.
Any suggestions?
You can move the identified by stakeholderId to the abstract participation as mentioned below.
abstract participant Stakeholder identified by stakeholderId{
o String stakeholderId
o String name
o Address address
o String email optional
o String telephone optional
o Certification certification optional
o String[] images optional
o Company company
o String username
o String password
}
participant Farmer extends Stakeholder {
o String description optional
--> Farm[] farms
}
To query for getUserFromUsername
query getUserFromUsername{
description:"get user from username"
statement:
SELECT org.ucsc.agriblockchain.Farmer
WHERE (username == _$username)
}
Because it is an abstract type, there is no data for the "Stakeholder" registry. You need to query the Farmer registry ... SELECT org.ucsc.agriblockchain.Farmer ...
Changing Stakeholkder from abstract to concrete won't help either if Farmer extends it because the Farmer will still be part of the Farmer registry.
I'm not sure exactly what you are wanting to achieve from the model, but you could revert to a single Participant type with optional fields for the different Stakeholder types, otherwise just write separate queries for the different Participant Types, and collate the results yourself in your code.
Update Following Comment
That Query against the Farmer registry should work.
Couple of hints ...
If you have changed the model or the Query, remember to stop and restart the REST server so that it can Discover the changes.
If you have changed the model, create some new test data.
If you are testing with the REST server, when you enter the parameter for the username, do not use quotes round the value.
(If you still have problems, please post the whole model, the latest query, and some example data that you are using in JSON format.)
Related
I'm working with the interface py2neo to access the neo4j database out of python. I want to used the autogenerated Id column in an OGM model as a property. But my idea doesn't work. Please look a the example:
from py2neo import Graph, Node, Relationship
from py2neo.ogm import GraphObject, Property, RelatedTo, RelatedFrom
class Material(GraphObject):
id = Property()
name = Property()
description = Property()
I insert the values into the system:
mat_f01 = Node('Material', name='F01', description='Fert Product 01')
mat_f02 = Node('Material', name='F02', description='Fert Product 02')
In the neo4j browser the record are displayed as followed - with the id column:
<id>:178 description: Fert Product 02 name: F02
If I look to the same records in flask the Id column contains the value None. It should contain 177 and 178.
description id name
Fert Product 01 Fert None F01
Fert Product 03 Fert None F03
Many thanks in advance.
The node ID has no correlation with the properties on that node. It is more of an internal attribute, closer to the address of a variable than an auto-generated ID. It is exposed by Neo4j as a convenience but should not be used for anything that requires a stable node reference as it can't provide those guarantees of stability.
If you want a unique identifier property then I recommend a UUID4 hex string instead. You can generate one of these in Python via the uuid module, and it should be guaranteed unique for all practical purposes.
Hi iam new to Blockchain .. please help with this.
1.I have customer participant should able to store multiple assests.
2. How to query all products of a customer
namespace demo
participant Customer identified by customerId {
o String customerId
o String firstName
o String lastName
o String email
o String phone
o Address address optional
--> Product[] product optional // here i need to store multiple products that belongs to this customer
}
asset Product identified by productId{
o String productId
o productType producttype
o String productName
o String model
--> Customer owner optional
}
1-i think in your business case there is no meaning to add owner to each product because you already have array of assets(Products) which belongs to each Customer.
1.1-to save multiple assets in your product array this will be done in Transaction Processing Function in logic.js file
in the documentation link below you will find very useful information about how to implement it:
https://hyperledger.github.io/composer/latest/reference/js_scripts
1.2-as solution for query you are going to query this participant registry by the customerId and in the results you will find your array of products. as the following.
in the queries.qry file
query CurrentCustomer {
description: "Returns Certain Customer Details in This Registry"
statement:
SELECT demo.Customer
WHERE (customerId == _$customerId)
}
for better understanding about queries you can check the documentation link below:
https://hyperledger.github.io/composer/latest/tutorials/queries
2-the question here are you going to add new products to this array each time the customer will buy Product ?
so imagine your customer have bought 10,000 products and with multiple Customer with this rate your application performance will not be the best because retrieving this much of data and mutate it then update your participant(Customer).
you can instead build relation between customer and invoice and each invoice contains enum of Product will be represented as concept which will contains all product properties and in this case each invoice will have owner so you can query all invoices for certain customer.
I am just getting started with Hyperledger and am trying to create the following asset in the .cto file
asset Contract identified by contractId {
o String contractId
o Boolean[] services
}
where all instances of Contract will have a "services" array with a fixed length of 9 (i.e. it should be impossible for the user to create a contract with any other length.)
Does anyone know how I could accomplish this?
you should be able to use this regex eg. String myfield regex=/^[0-9]{9}$/ will make sure it must be 9 digits (if its all digits etc etc).
I am using spring-neo4j. I have an entity called User with properties (username, firstName, lastName) and firstName and lastName are optional properties.
Now I want to implement a user search query which will search across all three properties.
#Query(value = "start user=node:__types__(className='com.xxx.entity.User') where user.username =~ {0} or user.firstName =~ {0} or user.lastName =~ {0} return user")
List<User> searchByName(String keyword);
The query fails saying that:
The property 'firstName' does not exist on Node[21].
However, if I search only on username, it gives me the result. I tried using the ? operator for nullable properties:
#Query(value = "start user=node:__types__(className='com.xxx.entity.User') where user.username =~ {0} or user.firstName? =~ {0} or user.lastName? =~ {0} return user")
List<User> searchByName(String keyword);
But this will fetch me all the nodes where firstName or lastName are missing.
Any idea how do I implement this query?
Would
start user=node:__types__(className='com.xxx.entity.User')
where user.username =~ {0}
or (has(user.firstName) and user.firstName =~ {0})
or (has(user.lastName) and user.lastName =~ {0})
return user
work?
Edit:
There are many reasons for a query not to return data. If you want help with that, share sample data and the parameters you are passing with your query. Use Neo4j console to share data and put the link and parameter examples in your question.
Until then, this might be helpful:
Use ! instead of ?.
[--verbose]
In Neo4j 1.x you can indeed use the ? and ! syntax, but you are using them wrong. ? defaults to true when the property is missing, which means your query matches the nodes you want plus all nodes that don't have a firstName or that don't have a lastName. ! will default to false when the property is missing and therefore exclude those nodes. n.prop! = val is equivalent to the has(n.prop) and n.prop=val I used above. See Neo4j stable docs.
In Neo4j 2.0+ the !? syntax is removed. Non-existing properties default to null. Therefore n.prop=val will evaluate to false exactly when has(n.prop) does(*). This means that your original query would work in 2.0–the query would resolve a missing property as a non-match and it would neither break nor include all nodes that don't have firstName or lastName(**). See Neo4j milestone docs. You might as well use syntax that won't break when SpringDataNeo4j moves to Neo4j 2.0, so use has(n.prop) and n.prop=val which works on either version.
Also please see How to cypher query a neo4j DB with WHERE clause on sparse property.
(*)(except it won't if val=null)
(**)(unless you pass null as a parameter)
I'm using the following code to generate unique relationships
public Relationship createRelationshipTypeWithUniqueFactory(Index<Relationship> index,
String indexableKey, final String indexableValue,
final RelationshipType type, final Node start, final Node end) {
UniqueFactory<Relationship> factory = new UniqueFactory.UniqueRelationshipFactory(index) {
#Override
protected Relationship create(Map<String, Object> properties) {
Relationship r = start.createRelationshipTo(end, type);
return r;
}
};
return factory.getOrCreate(indexableKey, indexableValue);
}
The factory requires me to pass a key and value (for the Index) so it can enforce the uniqueness of the relationship.
However, i'm not sure on how to build up the key + value.
Lets assume the following:
A - [knows] -> B (A knows B) where A and B are identified by the property email address
I want this relation ship to be unique so that A has at most 1 KNOWN relationship with B of this type.
Also, this should prevent B from creating an additional relationship to A (as the KNOWS relationship is bi-directional).
What would the best value to choose? One of the e-mail addresses (for example the lexical sorted most important of the two)?
Can anyone shed any light on this?
Cheers,
Erik
You can use Cyphers CREATE UNIQUE feature, creating the relationship only if it doesn't exist no regarding the direction upon a second run, see http://console.neo4j.org/r/a4kc2k
START n=node:node_auto_index(name='Neo'), t= node:node_auto_index(name='The Architect')
CREATE UNIQUE n-[r:SPEAKES_WITH]-t
RETURN n AS Neo,r