gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

543 lines
34KB

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>12.3. Controlling Text Search</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets V1.79.1" /><link rel="prev" href="textsearch-tables.html" title="12.2. Tables and Indexes" /><link rel="next" href="textsearch-features.html" title="12.4. Additional Features" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">12.3. Controlling Text Search</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="textsearch-tables.html" title="12.2. Tables and Indexes">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="textsearch.html" title="Chapter 12. Full Text Search">Up</a></td><th width="60%" align="center">Chapter 12. Full Text Search</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="textsearch-features.html" title="12.4. Additional Features">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="TEXTSEARCH-CONTROLS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">12.3. Controlling Text Search</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="textsearch-controls.html#TEXTSEARCH-PARSING-DOCUMENTS">12.3.1. Parsing Documents</a></span></dt><dt><span class="sect2"><a href="textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES">12.3.2. Parsing Queries</a></span></dt><dt><span class="sect2"><a href="textsearch-controls.html#TEXTSEARCH-RANKING">12.3.3. Ranking Search Results</a></span></dt><dt><span class="sect2"><a href="textsearch-controls.html#TEXTSEARCH-HEADLINE">12.3.4. Highlighting Results</a></span></dt></dl></div><p>
  3. To implement full text searching there must be a function to create a
  4. <code class="type">tsvector</code> from a document and a <code class="type">tsquery</code> from a
  5. user query. Also, we need to return results in a useful order, so we need
  6. a function that compares documents with respect to their relevance to
  7. the query. It's also important to be able to display the results nicely.
  8. <span class="productname">PostgreSQL</span> provides support for all of these
  9. functions.
  10. </p><div class="sect2" id="TEXTSEARCH-PARSING-DOCUMENTS"><div class="titlepage"><div><div><h3 class="title">12.3.1. Parsing Documents</h3></div></div></div><p>
  11. <span class="productname">PostgreSQL</span> provides the
  12. function <code class="function">to_tsvector</code> for converting a document to
  13. the <code class="type">tsvector</code> data type.
  14. </p><a id="id-1.5.11.6.3.3" class="indexterm"></a><pre class="synopsis">
  15. to_tsvector([<span class="optional"> <em class="replaceable"><code>config</code></em> <code class="type">regconfig</code>, </span>] <em class="replaceable"><code>document</code></em> <code class="type">text</code>) returns <code class="type">tsvector</code>
  16. </pre><p>
  17. <code class="function">to_tsvector</code> parses a textual document into tokens,
  18. reduces the tokens to lexemes, and returns a <code class="type">tsvector</code> which
  19. lists the lexemes together with their positions in the document.
  20. The document is processed according to the specified or default
  21. text search configuration.
  22. Here is a simple example:
  23. </p><pre class="screen">
  24. SELECT to_tsvector('english', 'a fat cat sat on a mat - it ate a fat rats');
  25. to_tsvector
  26. -----------------------------------------------------
  27. 'ate':9 'cat':3 'fat':2,11 'mat':7 'rat':12 'sat':4
  28. </pre><p>
  29. </p><p>
  30. In the example above we see that the resulting <code class="type">tsvector</code> does not
  31. contain the words <code class="literal">a</code>, <code class="literal">on</code>, or
  32. <code class="literal">it</code>, the word <code class="literal">rats</code> became
  33. <code class="literal">rat</code>, and the punctuation sign <code class="literal">-</code> was
  34. ignored.
  35. </p><p>
  36. The <code class="function">to_tsvector</code> function internally calls a parser
  37. which breaks the document text into tokens and assigns a type to
  38. each token. For each token, a list of
  39. dictionaries (<a class="xref" href="textsearch-dictionaries.html" title="12.6. Dictionaries">Section 12.6</a>) is consulted,
  40. where the list can vary depending on the token type. The first dictionary
  41. that <em class="firstterm">recognizes</em> the token emits one or more normalized
  42. <em class="firstterm">lexemes</em> to represent the token. For example,
  43. <code class="literal">rats</code> became <code class="literal">rat</code> because one of the
  44. dictionaries recognized that the word <code class="literal">rats</code> is a plural
  45. form of <code class="literal">rat</code>. Some words are recognized as
  46. <em class="firstterm">stop words</em> (<a class="xref" href="textsearch-dictionaries.html#TEXTSEARCH-STOPWORDS" title="12.6.1. Stop Words">Section 12.6.1</a>), which
  47. causes them to be ignored since they occur too frequently to be useful in
  48. searching. In our example these are
  49. <code class="literal">a</code>, <code class="literal">on</code>, and <code class="literal">it</code>.
  50. If no dictionary in the list recognizes the token then it is also ignored.
  51. In this example that happened to the punctuation sign <code class="literal">-</code>
  52. because there are in fact no dictionaries assigned for its token type
  53. (<code class="literal">Space symbols</code>), meaning space tokens will never be
  54. indexed. The choices of parser, dictionaries and which types of tokens to
  55. index are determined by the selected text search configuration (<a class="xref" href="textsearch-configuration.html" title="12.7. Configuration Example">Section 12.7</a>). It is possible to have
  56. many different configurations in the same database, and predefined
  57. configurations are available for various languages. In our example
  58. we used the default configuration <code class="literal">english</code> for the
  59. English language.
  60. </p><p>
  61. The function <code class="function">setweight</code> can be used to label the
  62. entries of a <code class="type">tsvector</code> with a given <em class="firstterm">weight</em>,
  63. where a weight is one of the letters <code class="literal">A</code>, <code class="literal">B</code>,
  64. <code class="literal">C</code>, or <code class="literal">D</code>.
  65. This is typically used to mark entries coming from
  66. different parts of a document, such as title versus body. Later, this
  67. information can be used for ranking of search results.
  68. </p><p>
  69. Because <code class="function">to_tsvector</code>(<code class="literal">NULL</code>) will
  70. return <code class="literal">NULL</code>, it is recommended to use
  71. <code class="function">coalesce</code> whenever a field might be null.
  72. Here is the recommended method for creating
  73. a <code class="type">tsvector</code> from a structured document:
  74. </p><pre class="programlisting">
  75. UPDATE tt SET ti =
  76. setweight(to_tsvector(coalesce(title,'')), 'A') ||
  77. setweight(to_tsvector(coalesce(keyword,'')), 'B') ||
  78. setweight(to_tsvector(coalesce(abstract,'')), 'C') ||
  79. setweight(to_tsvector(coalesce(body,'')), 'D');
  80. </pre><p>
  81. Here we have used <code class="function">setweight</code> to label the source
  82. of each lexeme in the finished <code class="type">tsvector</code>, and then merged
  83. the labeled <code class="type">tsvector</code> values using the <code class="type">tsvector</code>
  84. concatenation operator <code class="literal">||</code>. (<a class="xref" href="textsearch-features.html#TEXTSEARCH-MANIPULATE-TSVECTOR" title="12.4.1. Manipulating Documents">Section 12.4.1</a> gives details about these
  85. operations.)
  86. </p></div><div class="sect2" id="TEXTSEARCH-PARSING-QUERIES"><div class="titlepage"><div><div><h3 class="title">12.3.2. Parsing Queries</h3></div></div></div><p>
  87. <span class="productname">PostgreSQL</span> provides the
  88. functions <code class="function">to_tsquery</code>,
  89. <code class="function">plainto_tsquery</code>,
  90. <code class="function">phraseto_tsquery</code> and
  91. <code class="function">websearch_to_tsquery</code>
  92. for converting a query to the <code class="type">tsquery</code> data type.
  93. <code class="function">to_tsquery</code> offers access to more features
  94. than either <code class="function">plainto_tsquery</code> or
  95. <code class="function">phraseto_tsquery</code>, but it is less forgiving about its
  96. input. <code class="function">websearch_to_tsquery</code> is a simplified version
  97. of <code class="function">to_tsquery</code> with an alternative syntax, similar
  98. to the one used by web search engines.
  99. </p><a id="id-1.5.11.6.4.3" class="indexterm"></a><pre class="synopsis">
  100. to_tsquery([<span class="optional"> <em class="replaceable"><code>config</code></em> <code class="type">regconfig</code>, </span>] <em class="replaceable"><code>querytext</code></em> <code class="type">text</code>) returns <code class="type">tsquery</code>
  101. </pre><p>
  102. <code class="function">to_tsquery</code> creates a <code class="type">tsquery</code> value from
  103. <em class="replaceable"><code>querytext</code></em>, which must consist of single tokens
  104. separated by the <code class="type">tsquery</code> operators <code class="literal">&amp;</code> (AND),
  105. <code class="literal">|</code> (OR), <code class="literal">!</code> (NOT), and
  106. <code class="literal">&lt;-&gt;</code> (FOLLOWED BY), possibly grouped
  107. using parentheses. In other words, the input to
  108. <code class="function">to_tsquery</code> must already follow the general rules for
  109. <code class="type">tsquery</code> input, as described in <a class="xref" href="datatype-textsearch.html#DATATYPE-TSQUERY" title="8.11.2. tsquery">Section 8.11.2</a>. The difference is that while basic
  110. <code class="type">tsquery</code> input takes the tokens at face value,
  111. <code class="function">to_tsquery</code> normalizes each token into a lexeme using
  112. the specified or default configuration, and discards any tokens that are
  113. stop words according to the configuration. For example:
  114. </p><pre class="screen">
  115. SELECT to_tsquery('english', 'The &amp; Fat &amp; Rats');
  116. to_tsquery
  117. ---------------
  118. 'fat' &amp; 'rat'
  119. </pre><p>
  120. As in basic <code class="type">tsquery</code> input, weight(s) can be attached to each
  121. lexeme to restrict it to match only <code class="type">tsvector</code> lexemes of those
  122. weight(s). For example:
  123. </p><pre class="screen">
  124. SELECT to_tsquery('english', 'Fat | Rats:AB');
  125. to_tsquery
  126. ------------------
  127. 'fat' | 'rat':AB
  128. </pre><p>
  129. Also, <code class="literal">*</code> can be attached to a lexeme to specify prefix matching:
  130. </p><pre class="screen">
  131. SELECT to_tsquery('supern:*A &amp; star:A*B');
  132. to_tsquery
  133. --------------------------
  134. 'supern':*A &amp; 'star':*AB
  135. </pre><p>
  136. Such a lexeme will match any word in a <code class="type">tsvector</code> that begins
  137. with the given string.
  138. </p><p>
  139. <code class="function">to_tsquery</code> can also accept single-quoted
  140. phrases. This is primarily useful when the configuration includes a
  141. thesaurus dictionary that may trigger on such phrases.
  142. In the example below, a thesaurus contains the rule <code class="literal">supernovae
  143. stars : sn</code>:
  144. </p><pre class="screen">
  145. SELECT to_tsquery('''supernovae stars'' &amp; !crab');
  146. to_tsquery
  147. ---------------
  148. 'sn' &amp; !'crab'
  149. </pre><p>
  150. Without quotes, <code class="function">to_tsquery</code> will generate a syntax
  151. error for tokens that are not separated by an AND, OR, or FOLLOWED BY
  152. operator.
  153. </p><a id="id-1.5.11.6.4.7" class="indexterm"></a><pre class="synopsis">
  154. plainto_tsquery([<span class="optional"> <em class="replaceable"><code>config</code></em> <code class="type">regconfig</code>, </span>] <em class="replaceable"><code>querytext</code></em> <code class="type">text</code>) returns <code class="type">tsquery</code>
  155. </pre><p>
  156. <code class="function">plainto_tsquery</code> transforms the unformatted text
  157. <em class="replaceable"><code>querytext</code></em> to a <code class="type">tsquery</code> value.
  158. The text is parsed and normalized much as for <code class="function">to_tsvector</code>,
  159. then the <code class="literal">&amp;</code> (AND) <code class="type">tsquery</code> operator is
  160. inserted between surviving words.
  161. </p><p>
  162. Example:
  163. </p><pre class="screen">
  164. SELECT plainto_tsquery('english', 'The Fat Rats');
  165. plainto_tsquery
  166. -----------------
  167. 'fat' &amp; 'rat'
  168. </pre><p>
  169. Note that <code class="function">plainto_tsquery</code> will not
  170. recognize <code class="type">tsquery</code> operators, weight labels,
  171. or prefix-match labels in its input:
  172. </p><pre class="screen">
  173. SELECT plainto_tsquery('english', 'The Fat &amp; Rats:C');
  174. plainto_tsquery
  175. ---------------------
  176. 'fat' &amp; 'rat' &amp; 'c'
  177. </pre><p>
  178. Here, all the input punctuation was discarded as being space symbols.
  179. </p><a id="id-1.5.11.6.4.11" class="indexterm"></a><pre class="synopsis">
  180. phraseto_tsquery([<span class="optional"> <em class="replaceable"><code>config</code></em> <code class="type">regconfig</code>, </span>] <em class="replaceable"><code>querytext</code></em> <code class="type">text</code>) returns <code class="type">tsquery</code>
  181. </pre><p>
  182. <code class="function">phraseto_tsquery</code> behaves much like
  183. <code class="function">plainto_tsquery</code>, except that it inserts
  184. the <code class="literal">&lt;-&gt;</code> (FOLLOWED BY) operator between
  185. surviving words instead of the <code class="literal">&amp;</code> (AND) operator.
  186. Also, stop words are not simply discarded, but are accounted for by
  187. inserting <code class="literal">&lt;<em class="replaceable"><code>N</code></em>&gt;</code> operators rather
  188. than <code class="literal">&lt;-&gt;</code> operators. This function is useful
  189. when searching for exact lexeme sequences, since the FOLLOWED BY
  190. operators check lexeme order not just the presence of all the lexemes.
  191. </p><p>
  192. Example:
  193. </p><pre class="screen">
  194. SELECT phraseto_tsquery('english', 'The Fat Rats');
  195. phraseto_tsquery
  196. ------------------
  197. 'fat' &lt;-&gt; 'rat'
  198. </pre><p>
  199. Like <code class="function">plainto_tsquery</code>, the
  200. <code class="function">phraseto_tsquery</code> function will not
  201. recognize <code class="type">tsquery</code> operators, weight labels,
  202. or prefix-match labels in its input:
  203. </p><pre class="screen">
  204. SELECT phraseto_tsquery('english', 'The Fat &amp; Rats:C');
  205. phraseto_tsquery
  206. -----------------------------
  207. 'fat' &lt;-&gt; 'rat' &lt;-&gt; 'c'
  208. </pre><p>
  209. </p><pre class="synopsis">
  210. websearch_to_tsquery([<span class="optional"> <em class="replaceable"><code>config</code></em> <code class="type">regconfig</code>, </span>] <em class="replaceable"><code>querytext</code></em> <code class="type">text</code>) returns <code class="type">tsquery</code>
  211. </pre><p>
  212. <code class="function">websearch_to_tsquery</code> creates a <code class="type">tsquery</code>
  213. value from <em class="replaceable"><code>querytext</code></em> using an alternative
  214. syntax in which simple unformatted text is a valid query.
  215. Unlike <code class="function">plainto_tsquery</code>
  216. and <code class="function">phraseto_tsquery</code>, it also recognizes certain
  217. operators. Moreover, this function should never raise syntax errors,
  218. which makes it possible to use raw user-supplied input for search.
  219. The following syntax is supported:
  220. </p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: bullet; "><li class="listitem" style="list-style-type: disc"><p>
  221. <code class="literal">unquoted text</code>: text not inside quote marks will be
  222. converted to terms separated by <code class="literal">&amp;</code> operators, as
  223. if processed by
  224. <code class="function">plainto_tsquery</code>.
  225. </p></li><li class="listitem" style="list-style-type: disc"><p>
  226. <code class="literal">"quoted text"</code>: text inside quote marks will be
  227. converted to terms separated by <code class="literal">&lt;-&gt;</code>
  228. operators, as if processed by <code class="function">phraseto_tsquery</code>.
  229. </p></li><li class="listitem" style="list-style-type: disc"><p>
  230. <code class="literal">OR</code>: logical or will be converted to
  231. the <code class="literal">|</code> operator.
  232. </p></li><li class="listitem" style="list-style-type: disc"><p>
  233. <code class="literal">-</code>: the logical not operator, converted to the
  234. the <code class="literal">!</code> operator.
  235. </p></li></ul></div><p>
  236. </p><p>
  237. Examples:
  238. </p><pre class="screen">
  239. SELECT websearch_to_tsquery('english', 'The fat rats');
  240. websearch_to_tsquery
  241. ----------------------
  242. 'fat' &amp; 'rat'
  243. (1 row)
  244. SELECT websearch_to_tsquery('english', '"supernovae stars" -crab');
  245. websearch_to_tsquery
  246. ----------------------------------
  247. 'supernova' &lt;-&gt; 'star' &amp; !'crab'
  248. (1 row)
  249. SELECT websearch_to_tsquery('english', '"sad cat" or "fat rat"');
  250. websearch_to_tsquery
  251. -----------------------------------
  252. 'sad' &lt;-&gt; 'cat' | 'fat' &lt;-&gt; 'rat'
  253. (1 row)
  254. SELECT websearch_to_tsquery('english', 'signal -"segmentation fault"');
  255. websearch_to_tsquery
  256. ---------------------------------------
  257. 'signal' &amp; !( 'segment' &lt;-&gt; 'fault' )
  258. (1 row)
  259. SELECT websearch_to_tsquery('english', '""" )( dummy \\ query &lt;-&gt;');
  260. websearch_to_tsquery
  261. ----------------------
  262. 'dummi' &amp; 'queri'
  263. (1 row)
  264. </pre><p>
  265. </p></div><div class="sect2" id="TEXTSEARCH-RANKING"><div class="titlepage"><div><div><h3 class="title">12.3.3. Ranking Search Results</h3></div></div></div><p>
  266. Ranking attempts to measure how relevant documents are to a particular
  267. query, so that when there are many matches the most relevant ones can be
  268. shown first. <span class="productname">PostgreSQL</span> provides two
  269. predefined ranking functions, which take into account lexical, proximity,
  270. and structural information; that is, they consider how often the query
  271. terms appear in the document, how close together the terms are in the
  272. document, and how important is the part of the document where they occur.
  273. However, the concept of relevancy is vague and very application-specific.
  274. Different applications might require additional information for ranking,
  275. e.g., document modification time. The built-in ranking functions are only
  276. examples. You can write your own ranking functions and/or combine their
  277. results with additional factors to fit your specific needs.
  278. </p><p>
  279. The two ranking functions currently available are:
  280. </p><div class="variablelist"><dl class="variablelist"><dt><span class="term">
  281. <a id="id-1.5.11.6.5.3.1.1.1.1" class="indexterm"></a>
  282. <code class="literal">ts_rank([<span class="optional"> <em class="replaceable"><code>weights</code></em> <code class="type">float4[]</code>, </span>] <em class="replaceable"><code>vector</code></em> <code class="type">tsvector</code>, <em class="replaceable"><code>query</code></em> <code class="type">tsquery</code> [<span class="optional">, <em class="replaceable"><code>normalization</code></em> <code class="type">integer</code> </span>]) returns <code class="type">float4</code></code>
  283. </span></dt><dd><p>
  284. Ranks vectors based on the frequency of their matching lexemes.
  285. </p></dd><dt><span class="term">
  286. <a id="id-1.5.11.6.5.3.1.2.1.1" class="indexterm"></a>
  287. <code class="literal">ts_rank_cd([<span class="optional"> <em class="replaceable"><code>weights</code></em> <code class="type">float4[]</code>, </span>] <em class="replaceable"><code>vector</code></em> <code class="type">tsvector</code>, <em class="replaceable"><code>query</code></em> <code class="type">tsquery</code> [<span class="optional">, <em class="replaceable"><code>normalization</code></em> <code class="type">integer</code> </span>]) returns <code class="type">float4</code></code>
  288. </span></dt><dd><p>
  289. This function computes the <em class="firstterm">cover density</em>
  290. ranking for the given document vector and query, as described in
  291. Clarke, Cormack, and Tudhope's "Relevance Ranking for One to Three
  292. Term Queries" in the journal "Information Processing and Management",
  293. 1999. Cover density is similar to <code class="function">ts_rank</code> ranking
  294. except that the proximity of matching lexemes to each other is
  295. taken into consideration.
  296. </p><p>
  297. This function requires lexeme positional information to perform
  298. its calculation. Therefore, it ignores any <span class="quote">“<span class="quote">stripped</span>”</span>
  299. lexemes in the <code class="type">tsvector</code>. If there are no unstripped
  300. lexemes in the input, the result will be zero. (See <a class="xref" href="textsearch-features.html#TEXTSEARCH-MANIPULATE-TSVECTOR" title="12.4.1. Manipulating Documents">Section 12.4.1</a> for more information
  301. about the <code class="function">strip</code> function and positional information
  302. in <code class="type">tsvector</code>s.)
  303. </p></dd></dl></div><p>
  304. </p><p>
  305. For both these functions,
  306. the optional <em class="replaceable"><code>weights</code></em>
  307. argument offers the ability to weigh word instances more or less
  308. heavily depending on how they are labeled. The weight arrays specify
  309. how heavily to weigh each category of word, in the order:
  310. </p><pre class="synopsis">
  311. {D-weight, C-weight, B-weight, A-weight}
  312. </pre><p>
  313. If no <em class="replaceable"><code>weights</code></em> are provided,
  314. then these defaults are used:
  315. </p><pre class="programlisting">
  316. {0.1, 0.2, 0.4, 1.0}
  317. </pre><p>
  318. Typically weights are used to mark words from special areas of the
  319. document, like the title or an initial abstract, so they can be
  320. treated with more or less importance than words in the document body.
  321. </p><p>
  322. Since a longer document has a greater chance of containing a query term
  323. it is reasonable to take into account document size, e.g., a hundred-word
  324. document with five instances of a search word is probably more relevant
  325. than a thousand-word document with five instances. Both ranking functions
  326. take an integer <em class="replaceable"><code>normalization</code></em> option that
  327. specifies whether and how a document's length should impact its rank.
  328. The integer option controls several behaviors, so it is a bit mask:
  329. you can specify one or more behaviors using
  330. <code class="literal">|</code> (for example, <code class="literal">2|4</code>).
  331. </p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: bullet; "><li class="listitem" style="list-style-type: disc"><p>
  332. 0 (the default) ignores the document length
  333. </p></li><li class="listitem" style="list-style-type: disc"><p>
  334. 1 divides the rank by 1 + the logarithm of the document length
  335. </p></li><li class="listitem" style="list-style-type: disc"><p>
  336. 2 divides the rank by the document length
  337. </p></li><li class="listitem" style="list-style-type: disc"><p>
  338. 4 divides the rank by the mean harmonic distance between extents
  339. (this is implemented only by <code class="function">ts_rank_cd</code>)
  340. </p></li><li class="listitem" style="list-style-type: disc"><p>
  341. 8 divides the rank by the number of unique words in document
  342. </p></li><li class="listitem" style="list-style-type: disc"><p>
  343. 16 divides the rank by 1 + the logarithm of the number
  344. of unique words in document
  345. </p></li><li class="listitem" style="list-style-type: disc"><p>
  346. 32 divides the rank by itself + 1
  347. </p></li></ul></div><p>
  348. If more than one flag bit is specified, the transformations are
  349. applied in the order listed.
  350. </p><p>
  351. It is important to note that the ranking functions do not use any global
  352. information, so it is impossible to produce a fair normalization to 1% or
  353. 100% as sometimes desired. Normalization option 32
  354. (<code class="literal">rank/(rank+1)</code>) can be applied to scale all ranks
  355. into the range zero to one, but of course this is just a cosmetic change;
  356. it will not affect the ordering of the search results.
  357. </p><p>
  358. Here is an example that selects only the ten highest-ranked matches:
  359. </p><pre class="screen">
  360. SELECT title, ts_rank_cd(textsearch, query) AS rank
  361. FROM apod, to_tsquery('neutrino|(dark &amp; matter)') query
  362. WHERE query @@ textsearch
  363. ORDER BY rank DESC
  364. LIMIT 10;
  365. title | rank
  366. -----------------------------------------------+----------
  367. Neutrinos in the Sun | 3.1
  368. The Sudbury Neutrino Detector | 2.4
  369. A MACHO View of Galactic Dark Matter | 2.01317
  370. Hot Gas and Dark Matter | 1.91171
  371. The Virgo Cluster: Hot Plasma and Dark Matter | 1.90953
  372. Rafting for Solar Neutrinos | 1.9
  373. NGC 4650A: Strange Galaxy and Dark Matter | 1.85774
  374. Hot Gas and Dark Matter | 1.6123
  375. Ice Fishing for Cosmic Neutrinos | 1.6
  376. Weak Lensing Distorts the Universe | 0.818218
  377. </pre><p>
  378. This is the same example using normalized ranking:
  379. </p><pre class="screen">
  380. SELECT title, ts_rank_cd(textsearch, query, 32 /* rank/(rank+1) */ ) AS rank
  381. FROM apod, to_tsquery('neutrino|(dark &amp; matter)') query
  382. WHERE query @@ textsearch
  383. ORDER BY rank DESC
  384. LIMIT 10;
  385. title | rank
  386. -----------------------------------------------+-------------------
  387. Neutrinos in the Sun | 0.756097569485493
  388. The Sudbury Neutrino Detector | 0.705882361190954
  389. A MACHO View of Galactic Dark Matter | 0.668123210574724
  390. Hot Gas and Dark Matter | 0.65655958650282
  391. The Virgo Cluster: Hot Plasma and Dark Matter | 0.656301290640973
  392. Rafting for Solar Neutrinos | 0.655172410958162
  393. NGC 4650A: Strange Galaxy and Dark Matter | 0.650072921219637
  394. Hot Gas and Dark Matter | 0.617195790024749
  395. Ice Fishing for Cosmic Neutrinos | 0.615384618911517
  396. Weak Lensing Distorts the Universe | 0.450010798361481
  397. </pre><p>
  398. </p><p>
  399. Ranking can be expensive since it requires consulting the
  400. <code class="type">tsvector</code> of each matching document, which can be I/O bound and
  401. therefore slow. Unfortunately, it is almost impossible to avoid since
  402. practical queries often result in large numbers of matches.
  403. </p></div><div class="sect2" id="TEXTSEARCH-HEADLINE"><div class="titlepage"><div><div><h3 class="title">12.3.4. Highlighting Results</h3></div></div></div><p>
  404. To present search results it is ideal to show a part of each document and
  405. how it is related to the query. Usually, search engines show fragments of
  406. the document with marked search terms. <span class="productname">PostgreSQL</span>
  407. provides a function <code class="function">ts_headline</code> that
  408. implements this functionality.
  409. </p><a id="id-1.5.11.6.6.3" class="indexterm"></a><pre class="synopsis">
  410. ts_headline([<span class="optional"> <em class="replaceable"><code>config</code></em> <code class="type">regconfig</code>, </span>] <em class="replaceable"><code>document</code></em> <code class="type">text</code>, <em class="replaceable"><code>query</code></em> <code class="type">tsquery</code> [<span class="optional">, <em class="replaceable"><code>options</code></em> <code class="type">text</code> </span>]) returns <code class="type">text</code>
  411. </pre><p>
  412. <code class="function">ts_headline</code> accepts a document along
  413. with a query, and returns an excerpt from
  414. the document in which terms from the query are highlighted. The
  415. configuration to be used to parse the document can be specified by
  416. <em class="replaceable"><code>config</code></em>; if <em class="replaceable"><code>config</code></em>
  417. is omitted, the
  418. <code class="varname">default_text_search_config</code> configuration is used.
  419. </p><p>
  420. If an <em class="replaceable"><code>options</code></em> string is specified it must
  421. consist of a comma-separated list of one or more
  422. <em class="replaceable"><code>option</code></em><code class="literal">=</code><em class="replaceable"><code>value</code></em> pairs.
  423. The available options are:
  424. </p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: bullet; "><li class="listitem" style="list-style-type: disc"><p>
  425. <code class="literal">MaxWords</code>, <code class="literal">MinWords</code> (integers):
  426. these numbers determine the longest and shortest headlines to output.
  427. The default values are 35 and 15.
  428. </p></li><li class="listitem" style="list-style-type: disc"><p>
  429. <code class="literal">ShortWord</code> (integer): words of this length or less
  430. will be dropped at the start and end of a headline, unless they are
  431. query terms. The default value of three eliminates common English
  432. articles.
  433. </p></li><li class="listitem" style="list-style-type: disc"><p>
  434. <code class="literal">HighlightAll</code> (boolean): if
  435. <code class="literal">true</code> the whole document will be used as the
  436. headline, ignoring the preceding three parameters. The default
  437. is <code class="literal">false</code>.
  438. </p></li><li class="listitem" style="list-style-type: disc"><p>
  439. <code class="literal">MaxFragments</code> (integer): maximum number of text
  440. fragments to display. The default value of zero selects a
  441. non-fragment-based headline generation method. A value greater
  442. than zero selects fragment-based headline generation (see below).
  443. </p></li><li class="listitem" style="list-style-type: disc"><p>
  444. <code class="literal">StartSel</code>, <code class="literal">StopSel</code> (strings):
  445. the strings with which to delimit query words appearing in the
  446. document, to distinguish them from other excerpted words. The
  447. default values are <span class="quote">“<span class="quote"><code class="literal">&lt;b&gt;</code></span>”</span> and
  448. <span class="quote">“<span class="quote"><code class="literal">&lt;/b&gt;</code></span>”</span>, which can be suitable
  449. for HTML output.
  450. </p></li><li class="listitem" style="list-style-type: disc"><p>
  451. <code class="literal">FragmentDelimiter</code> (string): When more than one
  452. fragment is displayed, the fragments will be separated by this string.
  453. The default is <span class="quote">“<span class="quote"><code class="literal"> ... </code></span>”</span>.
  454. </p></li></ul></div><p>
  455. These option names are recognized case-insensitively.
  456. You must double-quote string values if they contain spaces or commas.
  457. </p><p>
  458. In non-fragment-based headline
  459. generation, <code class="function">ts_headline</code> locates matches for the
  460. given <em class="replaceable"><code>query</code></em> and chooses a
  461. single one to display, preferring matches that have more query words
  462. within the allowed headline length.
  463. In fragment-based headline generation, <code class="function">ts_headline</code>
  464. locates the query matches and splits each match
  465. into <span class="quote">“<span class="quote">fragments</span>”</span> of no more than <code class="literal">MaxWords</code>
  466. words each, preferring fragments with more query words, and when
  467. possible <span class="quote">“<span class="quote">stretching</span>”</span> fragments to include surrounding
  468. words. The fragment-based mode is thus more useful when the query
  469. matches span large sections of the document, or when it's desirable to
  470. display multiple matches.
  471. In either mode, if no query matches can be identified, then a single
  472. fragment of the first <code class="literal">MinWords</code> words in the document
  473. will be displayed.
  474. </p><p>
  475. For example:
  476. </p><pre class="screen">
  477. SELECT ts_headline('english',
  478. 'The most common type of search
  479. is to find all documents containing given query terms
  480. and return them in order of their similarity to the
  481. query.',
  482. to_tsquery('english', 'query &amp; similarity'));
  483. ts_headline
  484. ------------------------------------------------------------
  485. containing given &lt;b&gt;query&lt;/b&gt; terms +
  486. and return them in order of their &lt;b&gt;similarity&lt;/b&gt; to the+
  487. &lt;b&gt;query&lt;/b&gt;.
  488. SELECT ts_headline('english',
  489. 'Search terms may occur
  490. many times in a document,
  491. requiring ranking of the search matches to decide which
  492. occurrences to display in the result.',
  493. to_tsquery('english', 'search &amp; term'),
  494. 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=&lt;&lt;, StopSel=&gt;&gt;');
  495. ts_headline
  496. ------------------------------------------------------------
  497. &lt;&lt;Search&gt;&gt; &lt;&lt;terms&gt;&gt; may occur +
  498. many times ... ranking of the &lt;&lt;search&gt;&gt; matches to decide
  499. </pre><p>
  500. </p><p>
  501. <code class="function">ts_headline</code> uses the original document, not a
  502. <code class="type">tsvector</code> summary, so it can be slow and should be used with
  503. care.
  504. </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="textsearch-tables.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="textsearch.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="textsearch-features.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">12.2. Tables and Indexes </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 12.4. Additional Features</td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1