XQuery statement that groups results - group-by

I have an XML structure that I need to query using XQuery.
As far as I have been able to find, this may not even be possible, but since I am so new to XQuery I thought I may ask.
I need to query the XML below and return something that looks like:
<product>
<title>Acer Liquid</title>
<image>ACER-LIQUID.jpg</image>
<networks>
<network>O2O</network>
<network>VOD</network>
</networks>
<colours>
<colour>Blue</colour>
<colour>Black</colour>
</colours>
</product>
So my query is essentially something like:
Get all product details where there is a salespackage that belongs to "Pay Monthly" that points to it (via main_product), and attach the network property from each sales package that points to it. But group the results by the product.product_model field.
Source XML:
<root>
<package>
<title>package1</title>
<categories><category group="Other" name="Pay Monthly"/></categories>
<properties>
<value key="main_product">PRODUCT#14649766#PART#ACERLIQUIDBLACK</value>
<value key="network_code">O2O</value>
</properties>
</package>
<package>
<title>package2</title>
<categories><category group="Other" name="Pay Monthly"/></categories>
<properties>
<value key="main_product">PRODUCT#14649700#PART#ACERLIQUIDBLUE</value>
<value key="network_code">VOD</value>
</properties>
</package>
<product>
<title>Acer Liquid</title>
<properties>
<value key="product_code">PRODUCT#14649700#PART#ACERLIQUIDBLUE</value>
<value key="product_model">Acer Liquid|ACER_LIQUID</value>
<value key="product_image_url">ACER-LIQUID.jpg</value>
<value key="colour">Blue</value>
</properties>
</product>
<product>
<title>Acer Liquid</title>
<properties>
<value key="product_code">PRODUCT#14649766#PART#ACERLIQUIDBLACK</value>
<value key="product_model">Acer Liquid|ACER_LIQUID</value>
<value key="product_image_url">ACER-LIQUID.jpg</value>
<value key="colour">Black</value>
</properties>
</product>
</root>

Quite complex query for XQuery 1.0:
declare ordering unordered;
declare function local:values($items as node()*,
$property as xs:string) as xs:string* {
distinct-values($items/properties/value[#key eq $property])
};
declare function local:filter($items as node()*,
$property as xs:string,
$values as xs:string*) as node()* {
$items[properties/value[#key eq $property] = $values]
};
let $packages := doc('source')/root/package[categories/category[#name eq 'Pay Monthly']]
let $products := local:filter(doc('source')/root/product,
'product_code',
local:values($packages, 'main_product'))
for $model in local:values($products, 'product_model')
let $model_products := local:filter($products, 'product_model', $model)
let $model_packages := local:filter($packages,
'main_product',
local:values($model_products, 'product_code'))
return
<product>
{$model_products[1]/title}
<image>{local:values($model_products[1], 'product_image_url')}</image>
<networks>{
for $net in local:values($model_packages, 'network_code')
return <network>{$net}</network>
}</networks>
<colours>{
for $cl in local:values($model_products, 'colour')
return <colour>{$cl}</colour>
}</colours>
</product>

This XQuery:
for $title in (/root/product/title)[index-of(/root/product/title,.)[1]]
let $ProductsProp := /root/product[title=$title]/properties/value
return
<product>
{$title}
<image>{string(($ProductsProp[#key='product_image_url'])[1])}</image>
<networks>{
for $network in /root/package/properties
[value[#key='main_product']
= $ProductsProp[#key='product_code']]
/value[#key='network_code']/string()
return
<network>{$network}</network>
}</networks>
<colours>{
for $colour in $ProductsProp[#key='colour']/string()
return
<colour>{$colour}</colour>
}</colours>
</product>
Output:
<product>
<title>Acer Liquid</title>
<image>ACER-LIQUID.jpg</image>
<networks>
<network>O2O</network>
<network>VOD</network>
</networks>
<colours>
<colour>Blue</colour>
<colour>Black</colour>
</colours>
</product>
Note: XPath 2.0 grouping expression $vSeq[index-of($vSeq,.)[1]]

Related

SWXMLHash can't parse a [XMLIndexer]

I am trying for first time to parse a XML file and I am using SWXMLHash.
My xml file is:
<weatherdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://api.met.no/weatherapi/locationforecast/1.9/schema" created="2018-02-13T18:12:31Z">
<meta>
<model name="LOCAL" termin="2018-02-13T12:00:00Z" runended="2018-02-13T14:27:32Z" nextrun="2018-02-13T22:00:00Z" from="2018-02-13T19:00:00Z" to="2018-02-16T06:00:00Z" />
<model name="EPS" termin="2018-02-13T00:00:00Z" runended="2018-02-13T09:03:05Z" nextrun="2018-02-13T22:00:00Z" from="2018-02-16T12:00:00Z" to="2018-02-22T18:00:00Z" />
</meta>
<product class="pointData">
<time datatype="forecast" from="2018-02-13T19:00:00Z" to="2018-02-13T19:00:00Z">
<location altitude="0" latitude="" longitude="">
<temperature id="TTT" unit="celsius" value="3.5"/>
<windDirection id="dd" deg="158.8" name="S"/>
<windSpeed id="ff" mps="8.8" beaufort="5" name="Frisk bris"/>
<windGust id="ff_gust" mps="15.0"/>
<areaMaxWindSpeed mps="13.8"/>
<humidity value="82.1" unit="percent"/>
<pressure id="pr" unit="hPa" value="1002.5"/>
<cloudiness id="NN" percent="99.3"/>
<fog id="FOG" percent="0.0"/>
<lowClouds id="LOW" percent="73.2"/>
<mediumClouds id="MEDIUM" percent="0.0"/>
<highClouds id="HIGH" percent="91.0"/>
<dewpointTemperature id="TD" unit="celsius" value="0.6"/>
</location>
</time>
The <time> </time> repeates.
Having made a let parsedResultXML = SWXMLHash.parse(data)
I am trying to parse with a for in loop
for node in parsedResultXML["weatherdata"]["product"]["time"].all{
print(node)
}
I get results
<time to="2018-02-14T01:00:00Z" from="2018-02-14T01:00:00Z" datatype="forecast">
<location latitude="" longitude="" altitude="0">
<temperature id="TTT" unit="celsius" value="3.4"></temperature>
<windDirection id="dd" name="S" deg="158.7"></windDirection>
<windSpeed name="Liten kuling" mps="11.1" id="ff" beaufort="6"></windSpeed>
<windGust id="ff_gust" mps="19.0"></windGust>
<areaMaxWindSpeed mps="17.5"></areaMaxWindSpeed>
<humidity unit="percent" value="88.3"></humidity>
<pressure id="pr" unit="hPa" value="1002.5"></pressure>
<cloudiness id="NN" percent="99.3"></cloudiness>
<fog id="FOG" percent="0.1"></fog>
<lowClouds id="LOW" percent="98.6"></lowClouds>
<mediumClouds id="MEDIUM" percent="93.4"></mediumClouds>
<highClouds id="HIGH" percent="57.8"></highClouds>
<dewpointTemperature id="TD" unit="celsius" value="1.5"></dewpointTemperature>
</location>
</time>
But I can't access the elements.
Using
for node in parsedResultXML["weatherdata"]["product"]["time"].all{
node["time"].element?.attribute(by: "from")?.text
}
I don't get any results back.
Any idea??
Thanks
You're close... as #rmaddy commented, node is already indexed to "time". So instead of:
for node in parsedResultXML["weatherdata"]["product"]["time"].all {
node["time"].element?.attribute(by: "from")?.text
}
Do this instead:
for node in parsedResultXML["weatherdata"]["product"]["time"].all {
node.element?.attribute(by: "from")?.text
}

How to set default list user task assignee task Alfresco activiti with Java-backed

i'm trying to set users in task assignee to a workflow. here is my code :
List<ActivitiScriptNode> listPersonsScriptNode = new new ArrayList<ActivitiScriptNode>();
for (AssociationRef association : listePerosnsAssociation) {
listPersonsScriptNode.add(new ActivitiScriptNode(association.getTargetRef(), serviceRegistry));
}
workflowParameters.put(AssignationWorkflowModel.ASPECT_ASSIGNEVALIDATORS,
(Serializable) listPersonsScriptNode);
WorkflowPath wfPath = workflowService.startWorkflow(wid, workflowParameters);
and my model is :
<type name="wfav:assignationValideurTask">
<parent>bpm:workflowTask</parent>
<properties>
</properties>
<mandatory-aspects>
<aspect>wfav:assigneValidators</aspect>
</mandatory-aspects>
</type>
<aspects>
<aspect name="wfav:assigneValidators">
<associations>
<association name="wfav:assigneValidators">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:person</class>
<mandatory>true</mandatory>
<many>true</many>
</target>
</association>
</associations>
</aspect>
the error is : Couldn't deserialize object in variable 'wfav_assigneValidators'.
Has anyone get this error befor??
i have an isssu, i just change
List<ActivitiScriptNode>
with
ActivitiScriptNodeList

Inserting new tag in XML in xmlDB

Is it possible to insert new tag in the XML which is there in the XML-database?
For example; below is my example which is exists in the database:
<PurchaseOrder
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
"http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">
<Reference>SBELL-2002100912333601PDT</Reference>
<Actions>
<Action>
<User>SVOLLMAN</User>
</Action>
</Actions>
<Reject/>
<Requestor>Sarah J. Bell</Requestor>
<User>SBELL</User>
<CostCenter>S30</CostCenter>
<SpecialInstructions>Air Mail</SpecialInstructions>
<LineItems>
<LineItem ItemNumber="1">
<Description>A Night to Remember</Description>
<Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
</LineItems>
</PurchaseOrder>
I need to insert new tag <sender>xxxx</sender> where <costCente> is 'S30'.
After inserting/updating the XML, it should be like below:
<PurchaseOrder
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
"http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">
<Reference>SBELL-2002100912333601PDT</Reference>
<sender>xxx</sender>
<Actions>
<Action>
<User>SVOLLMAN</User>
</Action>
</Actions>
<Reject/>
<Requestor>Sarah J. Bell</Requestor>
<User>SBELL</User>
<CostCenter>S30</CostCenter>
<SpecialInstructions>Air Mail</SpecialInstructions>
<LineItems>
<LineItem ItemNumber="1">
<Description>A Night to Remember</Description>
<Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
</LineItems>
</PurchaseOrder>
Is it really a possible scenario?
Can any one give me query to do this, if it is possible.
Thanks in advance.
Below query worked for me.
UPDATE TABLENAME dd SET dd.object_value =
insertXMLbefore(dd.object_value,
'/c:PurchaseOrder/c:Reference',
XMLType('<d:sender xmlns:d="http://www.w3.org/2001/XMLSchema-instance">XXXX</d:sender>'),
xmlns:c="http://www.w3.org/2001/XMLSchema-instance"')
WHERE dd.id in (SELECT dd.id FROM TABLENAME dd,XMLTable(XMLNAMESPACES(
DEFAULT 'http://www.w3.org/2001/XMLSchema-instance' AS "c"),
'/PurchaseOrder' PASSING dd.object_value COLUMNS sender VARCHAR2(8 CHAR) PATH 'c:PurchaseOrder/c:Reference/text()',
rp VARCHAR2(8 CHAR) PATH 'CostCenter/text()') li
WHERE sender is null and rp = 'S30');

Alfresco API to run faceted search

I'm using Alfresco community 5.x version and I'm wondering if There are REST or any other remote alfresco apis to be able to run Faceted search.
I've seen some Restful apis to administer/manage some aspects of Faceted search viz : http://docs.alfresco.com/community5.0/references/RESTful-Facet.html
However no public APIs to run a faceted search.
I did notice that alfresco share fires the following against the core alfresco service to run its faceted search; but could not find any notes/docs related to that -
http://alfresco.mycompany.com/alfresco/s/slingshot/search
?facetFields={http://www.alfresco.org/model/content/1.0}creator,
{http://www.alfresco.org/model/content/1.0}content.mimetype,
{http://www.alfresco.org/model/content/1.0}created,
{http://www.alfresco.org/model/content/1.0}content.size,
{http://www.alfresco.org/model/content/1.0}modifier,
{http://www.alfresco.org/model/content/1.0}modified
&filters=
&term=wal
&tag=
&startIndex=0
&sort=
&site=
&rootNode=alfresco://company/home
&repo=false
&query=
&pageSize=25
&maxResults=0
&noCache=1455504682131
&spellcheck=true&
We have API based integration with Alfresco in our custom internal applications and don't use Alfresco Share.
I'm not sure if I should be using the above url or not.
Any suggestions on this?
Thanks!
Alfresco Version: 5.0.d
You can use the default search webscript:
webscripts\org\alfresco\slingshot\search\search.get.js
If you look at the code:
var params =
{
siteId: args.site,
containerId: args.container,
repo: (args.repo !== null) ? (args.repo == "true") : false,
term: args.term,
tag: args.tag,
query: args.query,
rootNode: args.rootNode,
sort: args.sort,
maxResults: (args.maxResults !== null) ? parseInt(args.maxResults, 10) : DEFAULT_MAX_RESULTS,
pageSize: (args.pageSize !== null) ? parseInt(args.pageSize, 10) : DEFAULT_PAGE_SIZE,
startIndex: (args.startIndex !== null) ? parseInt(args.startIndex, 10) : 0,
facetFields: args.facetFields,
filters: args.filters,
spell: (args.spellcheck !== null) ? (args.spellcheck == "true") : false
};
So if you present the right arguments with the facets to look for, then Alfresco will return the right faceted results.
I finally figured out how to implement and integrate the faceted search into a custom UI. the same also works with share.
create model in model manager (no hyphens)
Indexing attribute:
String: list of values whole match
Date, Number: enhanced search
For each type define the layout design - w/o this you wont be able to change type in share at least.
In share/search manager create filters/facets for fields you're interested in
Add a custom *context.xml to define a bean with your custom FacetQueryProvider implementation. inject that into the facet.solrFacetHelper bean
The custom FacetQueryProvider e.g. DollarAmountDisplayHandler basically provides facet queries based on the dollar amount buckets bean in the *context.xml, those will then be passed to solr.
Jar up the FacetQueryProvider implementation and copy to tomcat/lib directory.
Custom-solr-facets-context.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="facet.dateFacetFields" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet">
<set>
<value>#{http://www.alfresco.org/model/content/1.0}created</value>
<value>#{http://www.alfresco.org/model/content/1.0}modified</value>
<value>#{http://www.mycomp.com/model/hono/1.0}invoiceDate</value>
</set>
</property>
</bean>
<bean id="facet.dollarAmountBuckets" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="[0 TO 1000]" value="$0-$1K" />
<entry key="[1000 TO 10000]" value="$1K-$10K" />
<entry key="[10000 TO 100000]" value="$10K-$100K" />
<entry key="[100000 TO MAX]" value="Above.$100K" />
</map>
</property>
</bean>
<bean id="facet.dollarAmountDisplayHandler" class="com.mycomp.edm.alfresco.extensions.search.solr.facets.handlers.DollarAmountDisplayHandler" parent="baseFacetLabelDisplayHandler" >
<constructor-arg index="0">
<set>
<value>#{http://www.mycomp.com/model/hono/1.0}invoiceAmount</value>
</set>
</constructor-arg>
<constructor-arg index="1">
<ref bean="facet.dollarAmountBuckets" />
</constructor-arg>
</bean>
<bean id="facet.solrFacetHelper" class="org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper" >
<constructor-arg>
<list>
<ref bean="facet.contentSizeBucketsDisplayHandler" />
<ref bean="facet.dateBucketsDisplayHandler" />
<ref bean="facet.dollarAmountDisplayHandler" />
</list>
</constructor-arg>
<property name="specialFacetIds">
<set>
<value>SITE</value>
<value>TAG</value>
<value>ANCESTOR</value>
<value>PARENT</value>
<value>ASPECT</value>
<value>TYPE</value>
<value>OWNER</value>
</set>
</property>
</bean>
</beans>
The model:
<?xml version="1.0" encoding="UTF-8"?>
<model xmlns="http://www.alfresco.org/model/dictionary/1.0" name="hon:hono">
<description>hono model</description>
<author>amit</author>
<imports>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
</imports>
<namespaces>
<namespace uri="http://www.mycomp.com/model/hono/1.0" prefix="hon"/>
</namespaces>
<data-types/>
<constraints/>
<types>
<type name="hon:invoice">
<title>Invoice</title>
<description>invoice model</description>
<parent>cm:content</parent>
<properties>
<property name="hon:invoiceNumber">
<title>Invoice Number</title>
<type>d:int</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>TRUE</tokenised>
<facetable>true</facetable>
</index>
</property>
<property name="hon:invoiceAmount">
<title>Invoice Amount</title>
<type>d:int</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>TRUE</tokenised>
<facetable>true</facetable>
</index>
</property>
<property name="hon:invoiceDate">
<title>Invoice Date</title>
<type>d:date</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>TRUE</tokenised>
<facetable>true</facetable>
</index>
</property>
<property name="hon:organizationName">
<title>Organization Name</title>
<type>d:text</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>FALSE</tokenised>
<facetable>true</facetable>
</index>
</property>
<property name="hon:customerName">
<title>Customer Name</title>
<type>d:text</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>FALSE</tokenised>
<facetable>true</facetable>
</index>
</property>
</properties>
<associations/>
<overrides/>
<mandatory-aspects/>
</type>
</types>
<aspects/>
</model>
Facet Query Provider
package com.mycomp.edm.alfresco.extensions.search.solr.facets.handlers;
import org.alfresco.repo.search.impl.solr.facet.FacetQueryProvider;
import org.alfresco.repo.search.impl.solr.facet.SolrFacetConfigException;
import org.alfresco.repo.search.impl.solr.facet.handler.AbstractFacetLabelDisplayHandler;
import org.alfresco.repo.search.impl.solr.facet.handler.FacetLabel;
import org.springframework.extensions.surf.util.ParameterCheck;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Amit on 2/24/16.
*/
public class DollarAmountDisplayHandler extends AbstractFacetLabelDisplayHandler implements FacetQueryProvider {
private static final Pattern SIZE_RANGE_PATTERN = Pattern.compile("(\\[\\d+\\sTO\\s(\\d+|MAX)\\])");
private final Map<String, FacetLabel> facetLabelMap;
private final Map<String, List<String>> facetQueriesMap;
public DollarAmountDisplayHandler(Set<String> facetQueryFields, LinkedHashMap<String, String> dollarValueBucketMap)
{
System.out.println("instantiating bean DollarAmountDisplayHandler");
ParameterCheck.mandatory("facetQueryFields", facetQueryFields);
ParameterCheck.mandatory("dollarValueBucketMap", dollarValueBucketMap);
this.supportedFieldFacets = Collections.unmodifiableSet(facetQueryFields);
facetLabelMap = new HashMap<>(dollarValueBucketMap.size());
Map<String, List<String>> facetQueries = new LinkedHashMap<>(facetQueryFields.size());
for (String facetQueryField : facetQueryFields)
{
List<String> queries = new ArrayList<>();
int index = 0;
for (Map.Entry<String, String> bucket : dollarValueBucketMap.entrySet())
{
String sizeRange = bucket.getKey().trim();
Matcher matcher = SIZE_RANGE_PATTERN.matcher(sizeRange);
if (!matcher.find())
{
throw new SolrFacetConfigException(
"Invalid dollar value range. Example of a valid size range is: [0 TO 1000]");
}
// build the facet query. e.g. {http://www.mycomp.com/model/hono/1.0}invoiceAmount:[0 TO 1000]
String facetQuery = facetQueryField + ':' + sizeRange;
queries.add(facetQuery);
// indexOf('[') => 1
String sizeRangeQuery = sizeRange.substring(1, sizeRange.length() - 1);
sizeRangeQuery = sizeRangeQuery.replaceFirst("\\sTO\\s", "\"..\"");
facetLabelMap.put(facetQuery, new FacetLabel(sizeRangeQuery, bucket.getValue(), index++));
}
facetQueries.put(facetQueryField, queries);
}
this.facetQueriesMap = Collections.unmodifiableMap(facetQueries);
System.out.println("Bean DollarAmountDisplayHandler instantiated");
}
#Override
public FacetLabel getDisplayLabel(String value)
{
FacetLabel facetLabel = facetLabelMap.get(value);
return (facetLabel == null) ? new FacetLabel(value, value, -1) : facetLabel;
}
#Override
public Map<String, List<String>> getFacetQueries()
{
return this.facetQueriesMap;
}
}

Openejb with JPA - able to retrieve but cannot insert into database

I am using openejb as my standalone container to run my unit testcases, in all the test in all the tests i was able to retrieve the values but not able to insert or update. Even if i try entitymanager.merge(obj), it is selecting the value correctly but it is not updating it.
I am new to this , so please help me with this error
thanks in advance
my persistence.xml file
<persistence-unit name="test"
transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/OracleDS</jta-data-source>
.....entity classes.....
<properties>
<property name="eclipselink.target-server" value="JBoss" />
<property name="eclipselink.target-database" value="Oracle" />
<property name="eclipselink.logging.level" value="FINE" />
<property name="eclipselink.logging.parameters" value="true" />
</properties>
</persistence-unit>
my dao method
tp.setname("van");
tp.settype("vehicle");
//entityManager.getTransaction().begin();
entityManager.merge(tp);
//entityManager.getTransaction().commit();
Do the followings for
Persist new entity:
Transport tp = new Transport();
tp.setname("van");
tp.settype("vehicle");
entityManager.getTransaction().begin();
entityManager.persist(tp);
entityManager.getTransaction().commit();
Update existing entity:
Query qry = entityManager.createQuery("Select t from
Transport t where t.type ='vechicle'");
List list = qry.getResultList();
//assume result return single entity
Transport tp = list.get(0);
tp.setInspectionDone(new Date()) ;
entityManager.getTransaction().begin();
entityManager.merge(tp);
entityManager.getTransaction().commit();
I think you need to ad #Transactional annotation in your class or method