forked from marklogic-community/semantic-news-search
-
Notifications
You must be signed in to change notification settings - Fork 0
/
facet-lib.xqy
100 lines (82 loc) · 3.05 KB
/
facet-lib.xqy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(: This module implements the triples-based custom constraints.
If you type "cat:Sports" for example, it will use a
triple-range-query to find all documents in the "Sports"
category, as represented by OpenCalais-supplied RDF triples.
NOTE: the assumption is that the relevant triples are
stored with the document itself: in this case, in the
document's properties fragment.
We also facet on these values through the use of
path range indexes.
All facets are configured in application/config/facets.xml
:)
xquery version "1.0-ml";
module namespace facet = "http://marklogic.com/sem-app/facet-lib";
import module namespace search = "http://marklogic.com/appservices/search"
at "/MarkLogic/appservices/search/search.xqy";
import module namespace data = "http://marklogic.com/sem-app/data"
at "/lib/data-access.xqy";
declare default function namespace "http://www.w3.org/2005/xpath-functions";
declare option xdmp:mapping "false";
(: This function constructs a triple range query
against properties, which the Search API will
then combine with the rest of the user's query.
:)
declare function facet:parse(
$constraint-qtext as xs:string,
$right as schema-element(cts:query))
as schema-element(cts:query)
{
let $facet-name := substring-before($constraint-qtext,':'),
$rdf-property := $data:facet-configs[@name eq $facet-name]/@rdf-property/string(),
$prop-value := string($right),
$delim := if (contains($prop-value,' ')) then '"' else ''
return
<cts:properties-query qtextconst="{$facet-name}:{$delim}{$prop-value}{$delim}">
{
cts:triple-range-query((), sem:iri($rdf-property), $prop-value)
}
</cts:properties-query>
};
(: This function tells the Search API the source of the
constraint's facet values, e.g. the "category" field range index.
:)
declare function facet:start(
$constraint as element(search:constraint),
$query as cts:query?,
$facet-options as xs:string*,
$quality-weight as xs:double?,
$forests as xs:unsignedLong*)
as item()*
{
let $facet-name := $constraint/@name,
$index-name := $data:facet-configs[@name eq $facet-name]/@index-name/string()
for $val in cts:field-values($index-name, (), ($facet-options, "concurrent"), $query, $quality-weight, $forests)
return
<value name="{$val}" count="{cts:frequency($val)}"/>
};
(: In order to support concurrency, we return the final
facet values in a separate function call.
:)
declare function facet:finish(
$start as item()*,
$constraint as element(search:constraint),
$query as cts:query?,
$facet-options as xs:string*,
$quality-weight as xs:double?,
$forests as xs:unsignedLong*)
as element(search:facet)
{
<search:facet name="{$constraint/@name}">
{
for $val in $start
return
<search:facet-value name="{$val/@name}" count="{$val/@count}">
{ facet:displayValue($val/@name) }
</search:facet-value>
}
</search:facet>
};
(: Display slashes instead of underscores in facet values :)
declare private function facet:displayValue($val) {
translate($val,'_','/')
};