Skip to content

Instantly share code, notes, and snippets.

@joewiz
Last active December 27, 2015 21:09
Show Gist options
  • Save joewiz/f7044a582eab18cc26e0 to your computer and use it in GitHub Desktop.
Save joewiz/f7044a582eab18cc26e0 to your computer and use it in GitHub Desktop.
EXPath Facet Spec workbook
xquery version "3.0";
(:~ An implementation of facet:count as described in "Case 1: Simple facet based on existing attribute"
of the EXPath Facet Spec. Depends on eXist's util:eval() function to handle dynamic path expressions.
@see http://expath.org/spec/facet/20151225#case-1-simple-facet-based-on-existing-attribute
:)
import module namespace util="http://exist-db.org/xquery/util";
declare namespace facet = "http://expath.org/ns/facet";
declare function facet:count($results as item()*, $facet-definitions as element(facet:facet-definition)*) as element(facet:facets) {
<facet:facets>
<facet:facet name="{$facet-definitions/@name}">
{
for $r in $results
let $group-by-expression := concat('$r/', $facet-definitions/facet:group-by/facet:sub-path)
(: use util:eval() for dynamic evaluation of arbitrary paths in eXist :)
group by $g := util:eval($group-by-expression)
order by count($r) descending
return
<facet:key value="{ $g }" count="{ count($r) }"/>
}
</facet:facet>
</facet:facets>
};
let $sample :=
<sample>
<employee>
<name>John Doe</name>
<sex>Male</sex>
<organization>HR</organization>
<location>
<country>US</country>
<state>CA</state>
<city>Pleasanton</city>
<gps>
<longitude>-95.677068</longitude>
<latitude>37.0625</latitude>
</gps>
</location>
<age>21</age>
<employDate>2010-02-01</employDate>
<skills>
<skill>Word</skill>
<skill>Excel</skill>
<skill>Windows</skill>
</skills>
</employee>
<employee>
<name>Jane Joe</name>
<sex>Female</sex>
<organization>Finance</organization>
<location>
<country>US</country>
<state>CA</state>
<city>San Francisco</city>
<gps>
<longitude>-122.419416</longitude>
<latitude>37.77493</latitude>
</gps>
</location>
<age>18</age>
<employDate>2003-02-01</employDate>
<skills>
<skill>Word</skill>
<skill>Excel</skill>
<skill>PowerPoint</skill>
<skill>Linux</skill>
</skills>
</employee>
<employee>
<name>Steve</name>
<sex>Male</sex>
<organization>HR</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Seattle</city>
<gps>
<longitude>-122.332071</longitude>
<latitude>47.60621</latitude>
</gps>
</location>
<age>31</age>
<employDate>2010-04-01</employDate>
<skills>
<skill>OpenOffice</skill>
<skill>Word</skill>
</skills>
</employee>
<employee>
<name>Kylie</name>
<sex>Female</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Bellingham</city>
<gps>
<longitude>-122.488225</longitude>
<latitude>48.759553</latitude>
</gps>
</location>
<age>23</age>
<employDate>2010-06-01</employDate>
<skills>
<skill>Word</skill>
<skill>PowerPoint</skill>
</skills>
</employee>
<employee>
<name>Kyle</name>
<sex>Male</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Bellingham</city>
<gps>
<longitude>-122.499225</longitude>
<latitude>48.759553</latitude>
</gps>
</location>
<age>45</age>
<employDate>2009-06-01</employDate>
<skills>
<skill>PowerPoint</skill>
<skill>PhotoShop</skill>
</skills>
</employee>
<employee>
<name>Mike</name>
<sex>Male</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>OR</state>
<city>Eugene</city>
<gps>
<longitude>-123.086754</longitude>
<latitude>44.052069</latitude>
</gps>
</location>
<age>55</age>
<employDate>1999-06-01</employDate>
<skills>
<skill>PowerPoint</skill>
<skill>Negotiation</skill>
</skills>
</employee>
</sample>
let $employees := $sample/employee
let $facetDefinition :=
<facet:facet-definition name="Org">
<facet:group-by>
<facet:sub-path>organization</facet:sub-path>
</facet:group-by>
</facet:facet-definition>
return
facet:count($employees, $facetDefinition)
<facet:facets xmlns:facet="http://expath.org/ns/facet">
<facet:facet name="Org">
<facet:key value="Sales" count="3"/>
<facet:key value="HR" count="2"/>
<facet:key value="Finance" count="1"/>
</facet:facet>
</facet:facets>
xquery version "3.0";
(:~ An implementation of facet:count as described in "Case 2: Simple customized facet based on group-by function"
of the EXPath Facet Spec. Depends on eXist's util:eval() function to handle dynamic path expressions.
@see http://expath.org/spec/facet/20151225#case-2-simple-customized-facet-based-on-group-by-function
:)
import module namespace util="http://exist-db.org/xquery/util";
declare namespace facet = "http://expath.org/ns/facet";
declare function facet:count($results as item()*, $facet-definitions as element(facet:facet-definition)*) as element(facet:facets) {
<facet:facets>
<facet:facet name="{$facet-definitions/@name}">
{
for $r in $results
let $group-by-expression :=
if ($facet-definitions/facet:group-by/@function) then
concat($facet-definitions/facet:group-by/@function, '($r/', $facet-definitions/facet:group-by/facet:sub-path, ')')
else
concat('$r/', $facet-definitions/facet:group-by/facet:sub-path)
(: use util:eval() for dynamic evaluation of arbitrary paths in eXist :)
group by $g := util:eval($group-by-expression)
order by count($r) descending
return
<facet:key value="{ $g }" count="{ count($r) }"/>
}
</facet:facet>
</facet:facets>
};
declare function local:group-by-org($org as xs:string) {
if ($org = ('Sales', 'Finance')) then
'Sales and Finance'
else
'Other departments'
};
let $sample :=
<sample>
<employee>
<name>John Doe</name>
<sex>Male</sex>
<organization>HR</organization>
<location>
<country>US</country>
<state>CA</state>
<city>Pleasanton</city>
<gps>
<longitude>-95.677068</longitude>
<latitude>37.0625</latitude>
</gps>
</location>
<age>21</age>
<employDate>2010-02-01</employDate>
<skills>
<skill>Word</skill>
<skill>Excel</skill>
<skill>Windows</skill>
</skills>
</employee>
<employee>
<name>Jane Joe</name>
<sex>Female</sex>
<organization>Finance</organization>
<location>
<country>US</country>
<state>CA</state>
<city>San Francisco</city>
<gps>
<longitude>-122.419416</longitude>
<latitude>37.77493</latitude>
</gps>
</location>
<age>18</age>
<employDate>2003-02-01</employDate>
<skills>
<skill>Word</skill>
<skill>Excel</skill>
<skill>PowerPoint</skill>
<skill>Linux</skill>
</skills>
</employee>
<employee>
<name>Steve</name>
<sex>Male</sex>
<organization>HR</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Seattle</city>
<gps>
<longitude>-122.332071</longitude>
<latitude>47.60621</latitude>
</gps>
</location>
<age>31</age>
<employDate>2010-04-01</employDate>
<skills>
<skill>OpenOffice</skill>
<skill>Word</skill>
</skills>
</employee>
<employee>
<name>Kylie</name>
<sex>Female</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Bellingham</city>
<gps>
<longitude>-122.488225</longitude>
<latitude>48.759553</latitude>
</gps>
</location>
<age>23</age>
<employDate>2010-06-01</employDate>
<skills>
<skill>Word</skill>
<skill>PowerPoint</skill>
</skills>
</employee>
<employee>
<name>Kyle</name>
<sex>Male</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Bellingham</city>
<gps>
<longitude>-122.499225</longitude>
<latitude>48.759553</latitude>
</gps>
</location>
<age>45</age>
<employDate>2009-06-01</employDate>
<skills>
<skill>PowerPoint</skill>
<skill>PhotoShop</skill>
</skills>
</employee>
<employee>
<name>Mike</name>
<sex>Male</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>OR</state>
<city>Eugene</city>
<gps>
<longitude>-123.086754</longitude>
<latitude>44.052069</latitude>
</gps>
</location>
<age>55</age>
<employDate>1999-06-01</employDate>
<skills>
<skill>PowerPoint</skill>
<skill>Negotiation</skill>
</skills>
</employee>
</sample>
let $employees := $sample/employee
let $facetDefinition :=
<facet:facet-definition name="Org">
<facet:group-by function="local:group-by-org">
<facet:sub-path>organization</facet:sub-path>
</facet:group-by>
</facet:facet-definition>
return
facet:count($employees, $facetDefinition)
<facet:facets xmlns:facet="http://expath.org/ns/facet">
<facet:facet name="Org">
<facet:key value="Sales and Finance" count="4"/>
<facet:key value="Other departments" count="2"/>
</facet:facet>
</facet:facets>
xquery version "3.0";
(:~ An implementation of facet:count as described in "Case 3: Counting facets when the grouping key consists of more than 1 value"
of the EXPath Facet Spec. Depends on eXist's util:eval() function to handle dynamic path expressions.
Fails with err:XPTY0004, as predicted by the spec: "There is no equivalent XQuery using group-by-clause, because skill is
a repeatable element. Following XQuery will throw err:XPTY0004."
@see http://expath.org/spec/facet/20151225#case-3-counting-facets-when-the-grouping-key-consists-of-more-than-1-value
:)
import module namespace util="http://exist-db.org/xquery/util";
declare namespace facet = "http://expath.org/ns/facet";
declare function facet:count($results as item()*, $facet-definitions as element(facet:facet-definition)*) as element(facet:facets) {
<facet:facets>
<facet:facet name="{$facet-definitions/@name}">
{
for $r in $results
let $group-by-expression := concat('$r/', $facet-definitions/facet:group-by/facet:sub-path)
(: use util:eval() for dynamic evaluation of arbitrary paths in eXist :)
group by $g := util:eval($group-by-expression)
order by count($r) descending
return
<facet:key value="{ $g }" count="{ count($r) }"/>
}
</facet:facet>
</facet:facets>
};
let $sample :=
<sample>
<employee>
<name>John Doe</name>
<sex>Male</sex>
<organization>HR</organization>
<location>
<country>US</country>
<state>CA</state>
<city>Pleasanton</city>
<gps>
<longitude>-95.677068</longitude>
<latitude>37.0625</latitude>
</gps>
</location>
<age>21</age>
<employDate>2010-02-01</employDate>
<skills>
<skill>Word</skill>
<skill>Excel</skill>
<skill>Windows</skill>
</skills>
</employee>
<employee>
<name>Jane Joe</name>
<sex>Female</sex>
<organization>Finance</organization>
<location>
<country>US</country>
<state>CA</state>
<city>San Francisco</city>
<gps>
<longitude>-122.419416</longitude>
<latitude>37.77493</latitude>
</gps>
</location>
<age>18</age>
<employDate>2003-02-01</employDate>
<skills>
<skill>Word</skill>
<skill>Excel</skill>
<skill>PowerPoint</skill>
<skill>Linux</skill>
</skills>
</employee>
<employee>
<name>Steve</name>
<sex>Male</sex>
<organization>HR</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Seattle</city>
<gps>
<longitude>-122.332071</longitude>
<latitude>47.60621</latitude>
</gps>
</location>
<age>31</age>
<employDate>2010-04-01</employDate>
<skills>
<skill>OpenOffice</skill>
<skill>Word</skill>
</skills>
</employee>
<employee>
<name>Kylie</name>
<sex>Female</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Bellingham</city>
<gps>
<longitude>-122.488225</longitude>
<latitude>48.759553</latitude>
</gps>
</location>
<age>23</age>
<employDate>2010-06-01</employDate>
<skills>
<skill>Word</skill>
<skill>PowerPoint</skill>
</skills>
</employee>
<employee>
<name>Kyle</name>
<sex>Male</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>WA</state>
<city>Bellingham</city>
<gps>
<longitude>-122.499225</longitude>
<latitude>48.759553</latitude>
</gps>
</location>
<age>45</age>
<employDate>2009-06-01</employDate>
<skills>
<skill>PowerPoint</skill>
<skill>PhotoShop</skill>
</skills>
</employee>
<employee>
<name>Mike</name>
<sex>Male</sex>
<organization>Sales</organization>
<location>
<country>US</country>
<state>OR</state>
<city>Eugene</city>
<gps>
<longitude>-123.086754</longitude>
<latitude>44.052069</latitude>
</gps>
</location>
<age>55</age>
<employDate>1999-06-01</employDate>
<skills>
<skill>PowerPoint</skill>
<skill>Negotiation</skill>
</skills>
</employee>
</sample>
let $employees := $sample/employee
let $facetDefinition :=
<facet:facet-definition name="Skill">
<facet:group-by>
<facet:sub-path>skills/skill</facet:sub-path>
</facet:group-by>
</facet:facet-definition>
return
facet:count($employees, $facetDefinition)
<exception>
<path>/db/apps/facet/case-3.xq</path>
<message>
err:XPTY0004 Grouping variable g evaluates to more than one item [at line 164, column 5, source: /db/apps/facet/case-3.xq]
In function: facet:count(item()*, element()*) [164:5:/db/apps/facet/case-3.xq]
</message>
</exception>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment