hyperledger-composer query with "CONTAINS" operator not working - hyperledger-composer

In my hyperledger-composer app with angular front-end I want to send a query to the REST server.
query selectEmployeesByProject {
description: "Select all employees with access to the specified project"
statement:
SELECT org.comp.app.Employee
WHERE (projects CONTAINS [_$project])
ORDER BY [lastName, firstName]
}
Employee is defined as follows:
participant Employee {
o String lastName
o String firstName
--> Project[] projects optional
}
The http-request that is sent is the following:
this.httpClient.get<any[]>(requestURL, {withCredentials: true});
whereby the request url is the following:
http://localhost:4200/api/queries/selectEmployeesByProject?projects=resource:org.comp.app.Project#project1ID
In the console I get the following error message:
Failed to load resource
http://localhost:4200/api/queries/selectEmployeesByProject?projects=resource:org.comp.app.Project#project1ID
the server responded with a status of 400 (Bad Request)
Why is the query not working?
In general, httpRequests to the REST-server work in my app. Even other queries work. However, queries with the "CONTAINS" operator (such as the one above) do not work.

more likely to be
query selectClientsByProjects {
description: "Select all clients with access to a certain project"
statement:
SELECT org.myComp.myApp.Client
WHERE (projects CONTAINS [_$project])
ORDER BY [lastName ASC, firstName ASC]
}
Note: At the time of writing - CouchDB does not allow the ORDER BY clause to contain multiple items of different sort direction (obviously not the case above).
Also - not tested but your http call may need to be:
this.http.get('http://localhost:4200/api/queries/selectClientsByProjects?projects=resource:org.myComp.myApp.Project%231')
(%23 is the ASCII for '#')
You can try it out your definition first anyway (eg. without ORDER BY maybe) etc etc. Note: CONTAINS must match one entry ('array contains an element, with complete string match (above), in any element, in that array)

Related

How to Query Spring Data Neo4j with List Argument

I am trying to execute the query "find all merchants whose ids are in this list" (where the id is #GeneratedValue UUID string) in my spring data neo4j application.
Using query methods, that would (AFAIK) translate to either of:
List<Merchant> findByIdIn(List<String> ids);
List<Merchant> findByIdIsIn(List<String> ids);
In my swagger UI, I can see the endpoints, but when I pass in a valid id, no results are returned:
However, if I execute the same method programatically, the correct results are returned:
Similarly, the GET /merchants/90c55d4b-b3dc-4ae3-ab43-4d6ff523a20b endpoint returns the expected element.
This leads me to believe the internal translation of the HTTP request to the query isn't correct (most likely due to the list arg). The exact same thing happens (no results are returned) if I use a custom #Query, despite using the accepted solution from this s/o question:
#Query("MATCH (m: Merchant)" +
"WHERE m.id in $merchantId " +
"RETURN m")
List<Merchant> customQuery(List<String> merchantIds);
Am I missing something here? How do I query using a list as an argument? Thanks!

Oracle - JSON_VALUE returns NULL

I have a JSON string as below, and when I run the following query, it does not return anything. The JSON is valid, so am I missing something?
SELECT JSON_VALUE(json_content, '$.section_1') FROM messages;
{"section_1":{"section_publish":true,"section_body":"<p><b>Overview<\/b><\/p><p>Launched on 19\/06\/1992, the NUVEEN NEW YORK SELECT TAX-FREE INCOME (NXN) is a passively managed exchange traded fund designed to provide a broad exposure to<\/p>"}}
From the documentation:
The function uses the path expression to evaluate expr and find a scalar JSON value that matches, or satisfies, the path expression.
Your path expression would return a JSON object, not a scalar, I believe. That's an error and the default behavior is to return null. You could try adding an ERROR ON ERROR clause and seeing if that raises an error.
As eaolson stated, JSON_VALUE will only return a SCALAR value. If you want to return the JSON string contained in "section_1" you can use JSON_TABLE while using the keywords FORMAT JSON.
WITH
messages
AS
(SELECT '{"section_1":{"section_publish":true,"section_body":"<p><b>Overview<\/b><\/p><p>Launched on 19\/06\/1992, the NUVEEN NEW YORK SELECT TAX-FREE INCOME (NXN) is a passively managed exchange traded fund designed to provide a broad exposure to<\/p>"}}' AS json_content
FROM DUAL)
SELECT j.*
FROM messages
CROSS JOIN
JSON_TABLE (
json_content,
'$'
COLUMNS section1 FORMAT JSON PATH '$.section_1',
section1_publish PATH '$.section_1.section_publish',
section1_body PATH '$.section_1.section_body') j;

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

Composer query to match a participant reference

So I have a query like this:
query selectOrder{
description: "Select an Order that matches a Client reference and an Order Number"
statement:
SELECT com.x.Order
WHERE (client == _$client AND orderNumber == _$orderNumber)
}
The order is something like this:
asset Order identified by uuid {
o String uuid
--> Client client
o String orderNumber
--> Item[] items
}
How do I pass the reference to the client to the query?
I tried the reference and was told to toJSON it.
I tried that and it won't parse the thing - there's a clear issue with the parsing of the query.
I can't find the answer in the docs, so I'm wondering if anyone has done this or if I have to save the client id instead of the reference to client and lose the integrity.
EDIT: For completeness for the first answer below.
I'm trying to add an Item to the array of Items.
My Item object is defined like this:
asset Item identified by uuid {
o String uuid
o DateTime timestamp
o String orderNumber
--> Client client
o String[] message
}
When the transaction is invoked the single object passed in is the Item.
I'm setting Item.client as the _$client value in the query.
Should I be pre-pending it with "resource:"?
I'm asking because I thought that was in the reference string already - at least it is in the view in the playground.
EDIT2:
So I manually construct the following variable:
var RSRC = 'resource:com.x.Client#XYZ123'
Set that as the client in this query
return query('selectOrder', {agency : RSRC, orderNumber : orderNumber});
But I'm still getting this:
Error: unknown operator "0" - should be one of $eq, $lte, $lt, $gt,
$gte, $exists, $ne, $in, $nin, $size, $mod, $regex, $elemMatch, $type
or $all
What next?
Embedding the "resource..." string in quotes didn't work either.
Your query looks ok, but you need to pass a string with the format:
resource:type.Name#instance for the relationship.
E.g. resource:org.acme.Car#123ABC

Spring jdbcTemplate executing query

I have a strange problem ,
My Query looks like below.
String tokenQuery = "select id from table
where current_timestamp between
creation_time and (creation_time + interval '10' minute)
and token = '"+Token+"'";
But when I run, jdbcTemplate.queryForLong(tokenQuery) , no matter what , it always throws EmptyDataAccessException.
I am executing this in Oracle
Can we not append dynamic values to string and then pass it as a query and execute ?
What could be the issue ?
I assume that what you get is in fact an EmptyResultDataAccessException. The javadoc of this exception says:
Data access exception thrown when a result was expected to have at least one row (or element) but zero rows (or elements) were actually returned.
That simply means that the query is executed fine, and is supposed to return one row, but doesn't return any. So no row satisfies the criteria of your query.
If that is expected, then catch the exception, or use a method that returns a list rather then returning a single value. That way, you can test if the returned list is empty.
That said, you should use a parameterized query instead of concatenating the token like you're doing. This would prevent SQL injection attacks. It would also work even if the token contains a quote, for example.

Resources