forked from marklogic-community/semantic-news-search
-
Notifications
You must be signed in to change notification settings - Fork 0
/
snippet.xqy
83 lines (66 loc) · 2.69 KB
/
snippet.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
(: This module implements a custom snippeting function.
The only customization is that we expand the original query
in order to highlight examples of the requested class.
For example, if the original query contains 'org:"central bank"',
then the expanded query will contain OR'd word-queries for
"US Federal Reserve", "China's National Audit Office", etc.
causing such phrases to be highlighted in the results, even
though they weren't a part of the original query.
It does this by looking for an expandable triple-range-query in
the original query and then adding a bunch of word queries enumerated
from the result of a deeper dig into the RDF store via SPARQL.
:)
xquery version "1.0-ml";
module namespace snip = "http://marklogic.com/sem-app/snippet";
import module namespace sem = "http://marklogic.com/semantics"
at "/MarkLogic/semantics.xqy";
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 is the function that the Search API calls to retrieve
the custom snippet. The only thing we do is expand the query
and then pass it back to the built-in snippeting function.
:)
declare function snip:expanded-snippet(
$result as node(),
$ctsquery as schema-element(cts:query),
$options as element(search:transform-results)?
) as element(search:snippet)
{
let $expanded-query := snip:expand($ctsquery) return
search:snippet($result, $expanded-query, $options)
};
(: This function expands the query, according to whether
expandable predicates appear in the original.
:)
declare function snip:expand($query) {
let $word-queries :=
for $facet in $data:facet-configs[@expandable-via]
let $triple-constraints := $query//cts:triple-range-query
[cts:predicate = $facet/@rdf-property]
return
$triple-constraints
! snip:instances(cts:predicate, cts:object, $facet/@expandable-via)
! cts:word-query(.)
return
<cts:or-query>
{$query, $word-queries}
</cts:or-query>
};
(: This function calls out to SPARQL to get the actual
instance names (e.g. "Free Syrian Army") for the given
facet value (e.g. org:"governmental military").
:)
declare function snip:instances($facet, $value, $expand-prop) {
sem:sparql("
SELECT DISTINCT ?instanceName
WHERE {
?instance <"||$facet||"> '"||$value||"' ;
<"||$expand-prop||"> ?instanceName .
}
")
! map:get(., "instanceName")
};