Skip to content

Commit 0b19849

Browse files
committed
[bugfix] First pass at modifying the search for DockBook 5
1 parent 1510e7e commit 0b19849

File tree

2 files changed

+164
-107
lines changed

2 files changed

+164
-107
lines changed
Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,49 @@
11
<collection xmlns="http://exist-db.org/collection-config/1.0">
2-
<index>
2+
<index xmlns:db5="http://docbook.org/ns/docbook">
33
<fulltext default="none" attributes="false"/>
44
<lucene>
55
<analyzer class="org.apache.lucene.analysis.standard.StandardAnalyzer"/>
6-
<text qname="section">
7-
<ignore qname="title"/>
8-
<ignore qname="programlisting"/>
9-
<ignore qname="screen"/>
10-
<ignore qname="synopsis"/>
6+
7+
<!--
8+
Indexes below are ordered by their relevance (or "boost"),
9+
with the most relevant listed first.
10+
11+
Our definitions are based on the assumption that the most
12+
specific content will be deeper within the document.
13+
-->
14+
15+
<!-- document metadata -->
16+
<text qname="db5:keyword" boost="2.0"/>
17+
<text match="/db5:article/db5:info/db5:title" boost="1.7"/>
18+
<text match="/db5:article/db5:para" boost="1.5"/>
19+
20+
<!-- sect3 -->
21+
<text match="/db5:article/db5:sect1/db5:sect2/db5:sect3/db5:title" boost="1.35"/>
22+
<text qname="db5:sect3" boost="1.3">
23+
<ignore qname="db5:title"/>
24+
<ignore qname="db5:programlisting"/>
25+
<ignore qname="db5:screen"/>
26+
<ignore qname="db5:synopsis"/>
1127
</text>
12-
<text qname="title" boost="2.0"/>
13-
</lucene>
14-
<lucene>
15-
<analyzer class="org.apache.lucene.analysis.standard.StandardAnalyzer"/>
16-
<text qname="para"/>
17-
<text qname="title" boost="2.0"/>
18-
<ignore qname="title"/>
28+
29+
<!-- sect2 -->
30+
<text match="/db5:article/db5:sect1/db5:sect2/db5:title" boost="1.25"/>
31+
<text qname="db5:sect2" boost="1.2">
32+
<ignore qname="db5:title"/>
33+
<ignore qname="db5:programlisting"/>
34+
<ignore qname="db5:screen"/>
35+
<ignore qname="db5:synopsis"/>
36+
</text>
37+
38+
<!-- sect1 -->
39+
<text match="/db5:article/db5:sect1/db5:title" boost="1.15"/>
40+
<text qname="db5:sect1" boost="1.1">
41+
<ignore qname="db5:title"/>
42+
<ignore qname="db5:programlisting"/>
43+
<ignore qname="db5:screen"/>
44+
<ignore qname="db5:synopsis"/>
45+
</text>
46+
1947
</lucene>
2048
</index>
2149
</collection>

src/main/xar-resources/modules/search.xql

Lines changed: 123 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ xquery version "3.0";
33
(:~ ================================================
44
Implements the documentation search.
55
================================================ :)
6-
module namespace dq="http://exist-db.org/xquery/documentation/search";
6+
module namespace dq = "http://exist-db.org/xquery/documentation/search";
77

8-
import module namespace config="http://exist-db.org/xquery/apps/config" at "config.xqm";
8+
import module namespace config = "http://exist-db.org/xquery/apps/config" at "config.xqm";
99

10-
import module namespace kwic="http://exist-db.org/xquery/kwic";
10+
import module namespace kwic = "http://exist-db.org/xquery/kwic";
11+
import module namespace util = "http://exist-db.org/xquery/util";
1112

12-
declare namespace templates="http://exist-db.org/xquery/templates";
13+
declare namespace db5 = "http://docbook.org/ns/docbook";
14+
declare namespace templates = "http://exist-db.org/xquery/templates";
1315

1416
declare option exist:serialize "method=html media-type=text/html expand-xincludes=yes";
1517

@@ -20,54 +22,142 @@ declare variable $dq:CHARS_KWIC := 80;
2022
Templating function: process the query.
2123
:)
2224
declare
23-
%public %templates:default("field", "all") %templates:default("view", "summary")
24-
function dq:query($node as node()*, $model as map(*), $q as xs:string?, $field as xs:string, $view as xs:string) {
25+
%public
26+
%templates:default("field", "all")
27+
%templates:default("view", "summary")
28+
function dq:query($node as node()*, $model as map(*), $q as xs:string?, $field as xs:string, $view as xs:string) as element(div)? {
2529
if ($q) then
2630
let $hits := dq:do-query(collection($config:data-root), $q, $field)
27-
let $search-params :=
28-
string-join(
29-
map-pairs(function($k, $v) { $k || "=" || $v }, ("q", "field"), ($q, $field)),
30-
"&amp;"
31-
)
3231
return
3332
<div id="f-search">
34-
{dq:print-results($hits, $search-params, $view)}
33+
{
34+
dq:print-results($hits, map { "q": $q, "field": $field}, $view)
35+
}
3536
</div>
3637
else
3738
()
3839
};
3940

41+
(:~
42+
: Returns the elements for which the $query matches.
43+
:
44+
: @param context the nodes to search
45+
: @param query the full-text query
46+
: @param field the name of a field, if the query should be restricted to a specific field
47+
:
48+
: @return The elements that match the query, typically one of:
49+
: db5:title, db5:keyword, db5:para, db5:sect1, db5:sect2, db5:sect3.
50+
:)
51+
declare
52+
%public
53+
function dq:do-query($context as node()*, $query as xs:string?, $field as xs:string?) as element()* {
54+
switch ($field)
55+
case "title" return
56+
$context/db5:article/db5:info/db5:title[ft:query(., $query)]
57+
|
58+
$context//(db5:sect3|db5:sect2|db5:sect1)/db5:title[ft:query(., $query)]
59+
60+
default return
61+
$context//db5:keyword[ft:query(., $query)]
62+
|
63+
$context/db5:article/(db5:info/db5:title|db5:para)[ft:query(., $query)]
64+
|
65+
$context//(db5:sect3|db5:sect2|db5:sect1)/db5:title[ft:query(., $query)]
66+
|
67+
$context//(db5:sect3|db5:sect2|db5:sect1)[ft:query(., $query)]
68+
};
69+
70+
(:~
71+
Display the query results.
72+
:)
73+
declare
74+
%private
75+
function dq:print-results($hits as element()*, $search-params as map(xs:string, xs:string), $view as xs:string) {
76+
<div id="f-results">
77+
<p class="heading">Found {count($hits)} result{if (count($hits) eq 1) then "" else "s"}.</p>
78+
{
79+
if ($view eq 'summary') then
80+
for $hit in $hits
81+
let $score := ft:score($hit)
82+
order by $score descending
83+
return
84+
<div class="section">
85+
<span class="score">Score: {round-half-to-even($score, 2)}</span>
86+
<div class="headings">{ dq:print-headings($hit, $search-params) }</div>
87+
{ dq:print($hit, $search-params, $view) }
88+
</div>
89+
else
90+
<table class="kwic">
91+
{
92+
for $hit in $hits
93+
order by ft:score($hit) descending
94+
return (
95+
<tr>
96+
<td class="headings" colspan="3">
97+
{dq:print-headings($hit, $search-params)}
98+
</td>
99+
</tr>,
100+
dq:print($hit, $search-params, $view)
101+
)
102+
}
103+
</table>
104+
}
105+
</div>
106+
};
107+
108+
(:~
109+
Print the hierarchical context of a hit.
110+
:)
111+
declare
112+
%private
113+
function dq:print-headings($hit as element(), $search-params as map(xs:string, xs:string)) {
114+
let $search-params-uri-query := dq:to-uri-query($search-params)
115+
let $uri := util:document-name(root($hit)) || "?" || $search-params-uri-query || "&amp;id=D" || util:node-id($hit)
116+
return
117+
(
118+
<a href="{$uri}">{$hit/ancestor-or-self::db5:article/db5:info/db5:title/text()}</a>
119+
,
120+
for $sect at $pos in $hit/(ancestor-or-self::db5:sect3|ancestor-or-self::db5:sect2|ancestor-or-self::db5:sect1)
121+
let $nodeId := util:node-id($sect)
122+
let $uri := util:document-name(root($sect)) || "?" || $search-params-uri-query || "&amp;id=D" || $nodeId || "#D" || $nodeId
123+
return
124+
(" > ", <a href="{$uri}">{$sect/db5:title/text()}</a>)
125+
)
126+
};
127+
128+
40129
(:~
41130
Display the hits: this function iterates through all hits and calls
42131
kwic:summarize to print out a summary of each match.
43132
:)
44-
declare %private function dq:print($hit as element(), $search-params as xs:string, $view as xs:string)
45-
as element()* {
46-
let $nodeId := util:node-id($hit)
47-
let $uri := util:document-name(root($hit)) || "?" ||
48-
$search-params || "&amp;id=D" || $nodeId || "#D" || $nodeId
49-
let $config :=
50-
<config xmlns="" width="{if ($view eq 'summary') then $dq:CHARS_SUMMARY else $dq:CHARS_KWIC}"
51-
table="{if ($view eq 'summary') then 'no' else 'yes'}"
52-
link="{$uri}"/>
133+
declare
134+
%private
135+
function dq:print($hit as element(), $search-params as map(xs:string, xs:string), $view as xs:string) as element()* {
53136
let $matches := kwic:get-matches($hit)
54137
return
55138
if ($view eq "kwic") then
56-
for $ancestor in ($matches/ancestor::para | $matches/ancestor::title | $matches/ancestor::td | $matches/ancestor::note[not(para)])
139+
let $nodeId := util:node-id($hit)
140+
let $uri := util:document-name(root($hit)) || "?" || dq:to-uri-query($search-params) || "&amp;id=D" || $nodeId || "#D" || $nodeId
141+
let $config :=
142+
<config xmlns="" width="{if ($view eq 'summary') then $dq:CHARS_SUMMARY else $dq:CHARS_KWIC}"
143+
table="{if ($view eq 'summary') then 'no' else 'yes'}"
144+
link="{$uri}"/>
145+
146+
for $ancestor in ($matches/ancestor::db5:para | $matches/ancestor::db5:title | $matches/ancestor::db5:td | $matches/ancestor::db5:note[not(db5:para)])
57147
for $match in $ancestor//exist:match
58148
return
59149
kwic:get-summary($ancestor, $match, $config)
60150
else
61-
let $ancestors := ($matches/ancestor::para | $matches/ancestor::title | $matches/ancestor::td | $matches/ancestor::note[not(para)])
151+
let $ancestors := ($matches/ancestor::db5:para | $matches/ancestor::db5:title | $matches/ancestor::db5:td | $matches/ancestor::db5:note[not(db5:para)])
62152
return
63153
for $ancestor in $ancestors
64154
return
65155
dq:match-to-copy($ancestor)
66156
};
67157

68-
declare function dq:match-to-copy($element as element())
69-
as element()
70-
{
158+
declare
159+
%private
160+
function dq:match-to-copy($element as element()) as element() {
71161
element { node-name($element) } {
72162
$element/@*,
73163
for $child in $element/node()
@@ -82,72 +172,11 @@ as element()
82172
}
83173
};
84174

85-
(:~
86-
Print the hierarchical context of a hit.
87-
:)
88-
declare %private function dq:print-headings($section as element()*, $search-params as xs:string) {
89-
let $log := util:log("DEBUG", ("##$search-paramsxxx): ", $search-params))
90-
let $nodeId := util:node-id($section)
91-
let $uri :=
92-
util:document-name(root($section)) || "?" || $search-params || "&amp;id=D" || $nodeId
93-
return
94-
<a href="{$uri}">{$section/ancestor-or-self::chapter/title/text()}</a>,
95-
for $s at $p in $section/ancestor-or-self::section
96-
let $nodeId := util:node-id($s)
97-
let $uri :=
98-
util:document-name(root($s)) || "?" || $search-params || "&amp;id=D" || $nodeId || "#D" || $nodeId
99-
return
100-
(" > ", <a href="{$uri}">{$s/title/text()}</a>)
101-
};
102-
103-
(:~
104-
Display the query results.
105-
:)
106-
declare %private function dq:print-results($hits as element()*, $search-params as xs:string, $view as xs:string) {
107-
<div id="f-results">
108-
<p class="heading">Found {count($hits)} result{
109-
if (count($hits) eq 1) then "" else "s"}.</p>
110-
{
111-
if ($view eq 'summary') then
112-
for $section in $hits
113-
let $score := ft:score($section)
114-
order by $score descending
115-
return
116-
<div class="section">
117-
<span class="score">Score: {round-half-to-even($score, 2)}</span>
118-
<div class="headings">{ dq:print-headings($section, $search-params) }</div>
119-
{ dq:print($section, $search-params, $view) }
120-
</div>
121-
else
122-
<table class="kwic">
123-
{
124-
for $section in $hits
125-
order by ft:score($section) descending
126-
return (
127-
<tr>
128-
<td class="headings" colspan="3">
129-
{dq:print-headings($section, $search-params)}
130-
</td>
131-
</tr>,
132-
dq:print($section, $search-params, $view)
133-
)
134-
}
135-
</table>
136-
}
137-
</div>
138-
};
139-
140-
declare %public function dq:do-query($context as node()*, $query as xs:string, $field as xs:string) {
141-
if (count($context) > 1) then
142-
switch ($field)
143-
case "title" return
144-
$context//section[ft:query(.//title, $query)]
145-
default return
146-
$context//section[ft:query(.//title, $query)] | $context//section[ft:query(., $query)][not(section)]
147-
else
148-
switch ($field)
149-
case "title" return
150-
$context[.//section[ft:query(.//title, $query)]]
151-
default return
152-
$context[.//section[ft:query(.//title, $query)] or .//section[ft:query(., $query)][not(section)]]
175+
declare
176+
%private
177+
function dq:to-uri-query($search-params as map(xs:string, xs:string)) as xs:string {
178+
string-join(
179+
map:for-each($search-params, function($k, $v) { $k || "=" || $v }),
180+
"&amp;"
181+
)
153182
};

0 commit comments

Comments
 (0)