Corda - problem using VaultCustomQueryCriteria - blockchain

I'm trying to use a VaultCustomQueryCriteria (Corda - Java) with the aggregate function SUM, but I get no results.
If I use another VaultCustomQueryCriteria, the query works.
What am I doing wrong?
Below some examples:
Query OK:
QueryCriteria statusCriteria = new QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED);
Field name = ExampleSchemaV1.Ingestion.class.getDeclaredField("name");
QueryCriteria countCriteria = new QueryCriteria.VaultCustomQueryCriteria(Builder.equal(name, "Mark"));
List<StateAndRef<IngestionState>> results = rpcOps.vaultQueryByCriteria(countCriteria,IngestionState.class).getStates();
Query KO: (no results)
QueryCriteria statusCriteria = new QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED);
Field nr = ExampleSchemaV1.Ingestion.class.getDeclaredField("nr");
Field name = ExampleSchemaV1.Ingestion.class.getDeclaredField("name");
CriteriaExpression sumQta = Builder.sum(nr, Arrays.asList(name));
QueryCriteria sumQtaCriteria = new QueryCriteria.VaultCustomQueryCriteria(sumQta);
QueryCriteria criteria = statusCriteria.and(sumQtaCriteria);
List<StateAndRef<IngestionState>> results = rpcOps.vaultQueryByCriteria(criteria,IngestionState.class).getStates();

Each vault query returns a Vault.Page object. When performing a sum query, the result of the sum is accessible via Vault.Page.getOtherResults(), rather than via Vault.Page.getStates().
This is because the sum query doesn't return any actual states, but rather the result of a computation over these states.

Related

How to get the results of a stored procedure when using cfscript new StoredProc()

First time trying to use a stored procedure via cfscript and I can't figure out how to get the results. With a regular query I do something like this to get my result set:
queryResult = queryResult.execute().getResult();
With the stored procedure my code is:
queryResult = new storedProc( procedure = 'stpQueryMyResultSet', datasource = 'mydsn' );
queryResult = queryResult.execute();
writeDump(queryResult);
That returns 3 structs - prefix, procResultSets and procOutVariables, but I can't seem to figure out how to get my query results.
Thanks to #Ageax for pointing me to that page. Here's how I got it working (I also added in a param for max rows to return):
queryResult = new storedProc( procedure = 'stpQueryMyResultSet', datasource = 'mydsn' );
queryResult.addParam( type = 'in', cfsqltype = 'cf_sql_integer', value = '10');
queryResult.addProcResult( name = 'result' );
qResult = queryResult.execute().getProcResultSets().result;
writeDump(qResult);

Dynamodb pagination of 10 results

I have a message table which I would like to get the last 10 messages for that user and if they click more it would retrieve another 10 until there were no more message left. I could not see how to do this, so far I am able to get message based on time, but this is not exactly what I want. Reading through the documentation I can see it a method called LastEvaluatedKey, but where and how do I use this I can't find a working example of this. This is my code for time:
long startDateMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L);
long endDateMilli = (new Date()).getTime() - (5L*24L*60L*60L*1000L);
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
String startDate = df.format(startDateMilli);
String endDate = df.format(endDateMilli);
QuerySpec spec = new QuerySpec()
.withProjectionExpression("to,fr,sta,cr")
.withKeyConditionExpression("to = :v_to and cr between :v_start_dt and :v_end_dt")
.withValueMap(new ValueMap()
.withString(":v_id", username)
.withString(":v_start_dt", startDate)
.withString(":v_end_dt", endDate));
ItemCollection<QueryOutcome> items = table.query(spec);
System.out.println("\nfindRepliesPostedWithinTimePeriod results:");
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}
How can I modify this to eliminate the time based pagination and use instead a last 10 messages type of pagination?

List of instances with minimal date of their group

I'm working on a Java project, using Hibernate to administrate data on a SQL database.
I try to fetch a list of instances from the Database, that have a minimal timestamp of the group they share. The group is modeled by a container.
Here is a minimal model sketch:
#Entity
#Table(name = "object")
public class Object implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.Auto)
long obj_id;
#Column(name = "time_stamp", nullable = false)
Date timestamp;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "container_id", nullable = false)
Container con;
}
#Entity
#Table(name = "container")
public class Container{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long con_id;
#OneToMany(mappedBy = "container")
List<object> obj_list;
}
So there are some objects with a timestamp and containers that group these objects.
For example, there are two containers, con_a and con_b:
Container con_a:
con_id = 1
obj_list = {obj_a, obj_b}
Container con_b:
con_id = 2
obj_list = {obj_c}
And three objects, obj_a, obj_b, obj_c:
Object obj_a
obj_id = 1
timestamp = 10
con = con_a
Object obj_b
obj_id = 2
timestamp = 20
con = con_a
Object obj_c
obj_id = 3
timestamp = 30
con = con_b
The desired List in this example would look like:
List<Object> = {obj_a, obj_c}
I seem to move in a circle, as I do not even know where to "start" the query:
Criteria crit = session.createCriteria(Container.class). ...
or
Criteria crit = session.createCriteria(Object.class). ...
It seems both possible for me, but i just have no idea how to go on from any of those 2 possibilities.
Update [2014.07.11, 14:19]:
I tried and started the query with the Object class and used a Subquery:
Session session = getSession();
Transaction transaction = session.beginTransaction();
DetachedCriteria IdListOfGroupMinimum = DetachedCriteria.forClass(Object.class, "obj")
IdListOfGroupMinimum.createAlias("con.id", "containerId")
.setProjection(
.Projections.projectionList()
.add(Projections.property("obj.id"))
.add(Projections.min("obj.timestamp"))
.add(Projections.groupProperty("containerId")))
.setProjection(Projection.property("obj.id"));
Criteria objects = session.createCriteria(object.class, "obj")
objects.add(Subqueries.in("obj.id", IdListOfGroupMinimum));
List<Object> = objects.list();
But I received the following error:
javax.servlet.ServletException: org.hibernate.QueryException: not an association: id
I tried to do this:
SELECT * from Object
WHERE id IN (
SELECT obj.id
FROM Object obj
INNER JOIN (
SELECT obj.containerID, MIN(obj.timestamp) AS minimum
FROM Object obj
GROUP BY obj.containerID) subquery
ON obj.containerID = subquery.containerID
WHERE obj.timestamp = subquery.minimum
)
I found a solution for my problem which is probably not the most elegant one, but it works.
Mainly I used the SQL-Query that I already posted above:
Session session = getSession();
Transaction transaction = session.beginTransaction();
//This query fetches the IDs of the smallest objects in each group with
//regard to the timestamp
Query q = session.createSQLQuery(
"SELECT obj.id FROM Object obj "
+ "INNER JOIN ( "
+ "SELECT obj.containerID, MIN(obj.timestamp) AS minimum "
+ "FROM Object obj "
+ "GROUP BY obj.containerID) subquery "
+ "ON obj.containerID = subquery.containerID "
+ "WHERE obj.timestamp = subquery.minimum "
);
//This tells Hibernate that the result are values of type Long
q.addScalar("id", LongType.INSTANCE)
//Creates a list of the found IDs
#SuppressWarnings("unchecked")
List<Long> ids = q.list();
//Fetches all object with those IDs...
Criteria smallestOfEachGroup = session.createCriteria(Object.class)
.add(Restrictions.in("id", ids);
//...and saves them in a list.
#SuppressWarnings("unchecked")
List<Object> desiredList = smallestOfEachGroup.list()
try{
transaction.commit();
} catch(HibernateException e) {
transaction.rollback();
}
As all my sketches are not the real code, so there might be still naming errors.
Anyway, I hope this helps someone.
I still would be pleased by any more elegant solution.
Update [2014.07.20, 18:50]:
I found a solution that uses Hibernate Criteria exclusively :)
Session session = getSession();
Transaction transaction = session.beginTransaction();
//This subquery fetches the minimal timestamp of a container.
DetachedCriteria minOfGroup = DetachedCriteria.forClass(Object.class);
minOfGroup.add(Restrictions.eqProperty("con.con_id", "outerObject.con.con_id")
.setProjection(Projections.min("timestamp"));
//This subquery fetches the IDs of all Objects, whose timestamp is minimal
//in their container.
DetachedCriteria groupwiseMin = DetachedCriteria.forClass(Object.class, "outerObject");
groupwiseMin.add(Subqueries.propertyEq("timestamp", minOfGroup));
.setProjections(Projections.id())
//This subquery fetches all Objects whose IDs are fetched by the groupwiseMin
//query
Criteria groupwiseMinObjects = session.createCriteria(Object.class);
groupwiseMinObjects.add(Subqueries.propertyIn("obj_id", groupwiseMin));
List<Object> desiredObjects = groupwiseMinObjects.list();
try{
transaction.commit();
} catch(HibernateException e) {
transaction.rollback();
}
I think you can make this query even shorter, if you remove the groupwiseMinObjects query above replace the groupwiseMin query by:
Criteria anotherGroupWiseMinObjects = session.createCriteria(Object.class, "outerObject");
anotherGroupwiseMinObjects.add(Subqueries.propertyEq("timestamp", minOfGroup));
But I did not test that.
In my original project I use several subqueries that converge in a single query.
That means after some subqueries, there is a final query like:
Criteria finalQuery = session.createCriteria(Object.class);
finalQuery.add(Subqueries. (...) )
(...)
.add(Subqueries. (...) );

count * with where clause using JPA criteria query

I want to find records for related_elements table, where relationId belongs to a list
suppose a Set tempSet contains[2,3,4]
I have to check for these value contains in related_element table using jpa criteria query
CriteriaBuilder cb1=entityManager.getCriteriaBuilder();
CriteriaQuery<RelatedElements> cq1=cb1.createQuery(RelatedElements.class);
Root<RelatedElements> RelatedElementsRoot=cq1.from(RelatedElements.class);
for (Integer tSet : tempSet) {
ParameterExpression<Integer> pRelatedElement=cb1.parameter(Integer.class);
cq1.multiselect(cb1.count(RelatedElementsRoot.<RelatedElements>get("relatedElementsPk").<Integer>get("relationId"))).where(cb1.equal(RelatedElementsRoot.get("relationId"), pRelatedElement));
TypedQuery<RelatedElements> qry = entityManager.createQuery(cq1);
qry.setParameter(pRelatedElement, tSet);
count = entityManager.createQuery(cq1).getSingleResult().getRelationId();
}
but its now working...any suggessions
second try
CriteriaBuilder cb1=entityManager.getCriteriaBuilder();
CriteriaQuery<Integer> cq1 = cb1.createQuery(Integer.class);
Root<RelatedElements> RelatedElementsRoot=cq1.from(RelatedElements.class);
for (Integer tSet : tempSet) {
ParameterExpression<Integer> pRelatedElement=cb1.parameter(Integer.class);
cq1.multiselect(cb1.count(cq1.from(RelatedElements.class)));
cq1.where((cb1.equal(RelatedElementsRoot.get("relatedElementsPk").get("relationId"), pRelatedElement)));
TypedQuery<Integer> qry = entityManager.createQuery(cq1);
qry.setParameter(pRelatedElement, tSet);
count =qry.getSingleResult();
}
its giving exception at qry.setParameter
Unable to locate appropriate constructor on class [java.lang.Integer] [select new java.lang.Integer(count(*)) from com.mcd.webex.model.RelatedElements as generatedAlias0, com.mcd.webex.model.RelatedElements as generatedAlias1 where generatedAlias0.relatedElementsPk.relationId=:param0]
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Dzialy> root = cq.from(Dzialy.class);
EntityType <Dzialy> Dzialy_ = root.getModel();
cq.select((cb.countDistinct(root)));
cq.where( cb.equal( root.get(Dzialy_.getSingularAttribute("DZI_id")), 1) );
long l = em.createQuery(cq).getSingleResult();
em - EntityManager
DZI_id - column name
1 - searching value
Dzialy - entity class
As documented, CriteriaBuilder.count returns Expression<java.lang.Long>. Consequently type argument to CriteriaQuery and TypedQuery should be Long as well. Same holds true for type of count variable.
When there is only one value to be selected, then it makes sense to use CriteriaQuery.select instead of multiselect, because then such an error is catched already in compile time.
Long count;
...
CriteriaQuery<Long> cq1 = cb1.createQuery(Long.class);
...
cq1.select(cb1.count(cq1.from(RelatedElements.class)));
...
TypedQuery<Long> qry = entityManager.createQuery(cq1);
CriteriaBuilder qb = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = qb.createQuery(Long.class);
cq.select(qb.count(cq.from(YourEntity.class)));
cq.where(/*your stuff*/);
return entityManager.createQuery(cq).getSingleResult();

Why is this CAML Query is not filtering results from SharePoint Web Service call?

I am trying to filter the list of results returned by the following web service call to a SharePoint list. When I have
query.InnerText = "";
the results include every row in the SharePoint list - including rows having an IN SERVICE DATE less than today, greater than today, or no value at all. I need the CAML query to filter, but adding the Where statement does not work.
service.Url = url;
String pipeProjectSummaryListGuid = "{2D193799-F1FB-46B1-A313-56B8B12E1111}";
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlElement query = xmlDoc.CreateElement("Query");
XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");
String rowLimit = "9000";
query.InnerText = "<Where><Gt><FieldRef Name=\"In_x0020_Service_x0020_Date\" /><Value Type=\"DateTime\"><Today /></Value></Gt></Where>";
viewFields.InnerXml = "<FieldRef Name=\"NEW_ID\" /><FieldRef Name=\"In_x0020_Service_x0020_Date\" /><FieldRef Name=\"ProjectPriority\" />";
queryOptions.InnerXml = "<ViewAttributes Scope=\"Recursive\" /><IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>";
try
{
results = service.GetListItems(pipeProjectSummaryListGuid, null, query, viewFields, rowLimit, queryOptions, null);
}
Try using query.InnerXml instead of query.InnerText.