Zend_Search_Lucene-Extending.xml 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 24249 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.search.lucene.extending">
  5. <title>Erweiterbarkeit</title>
  6. <sect2 id="zend.search.lucene.extending.analysis">
  7. <title>Textanalyse</title>
  8. <para>
  9. Die <classname>Zend_Search_Lucene_Analysis_Analyzer</classname> Klasse wird vom Indexer
  10. verwendet, um die Textfelder der Dokumente in Abschnitte aufzuteilen.
  11. </para>
  12. <para>
  13. Die <methodname>Zend_Search_Lucene_Analysis_Analyzer::getDefault()</methodname> und
  14. <methodname>Zend_Search_Lucene_Analysis_Analyzer::setDefault()</methodname> Methoden
  15. werden verwendet, um den Standardanalysator zu bekommen oder festzulegen.
  16. </para>
  17. <para>
  18. Man kann einen eigenen Textanalysator zuordnen oder ihn aus den vordefinierten
  19. Analysatoren auswählen:
  20. <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text</classname> und
  21. <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</classname>
  22. (Standard). Beide interpretieren einen Abschnitt als eine Sequenz aus Buchstaben.
  23. <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</classname>
  24. konvertiert alle Abschnitte in Kleinbuchstaben.
  25. </para>
  26. <para>
  27. Um zwischen Analysatoren zu wechseln:
  28. </para>
  29. <programlisting language="php"><![CDATA[
  30. Zend_Search_Lucene_Analysis_Analyzer::setDefault(
  31. new Zend_Search_Lucene_Analysis_Analyzer_Common_Text());
  32. ...
  33. $index->addDocument($doc);
  34. ]]></programlisting>
  35. <para>
  36. Die <classname>Zend_Search_Lucene_Analysis_Analyzer_Common</classname> Klasse wurde als
  37. Anker für alle benutzerdefinierten Analysatoren entwickelt. Benutzer sollten nur die
  38. <methodname>reset()</methodname> und <methodname>nextToken()</methodname> Methoden
  39. definieren, welche ihren String von der $_input Eigenschaft nimmt und die Abschnitte
  40. Stück für Stück zurückgibt (ein <constant>NULL</constant> Wert indiziert das Ende des
  41. Streams).
  42. </para>
  43. <para>
  44. Die <methodname>nextToken()</methodname> Methode sollte die
  45. <methodname>normalize()</methodname> Methode auf jedem Token aufrufen. Das erlaubt die
  46. Verwendung von Abschnittsfiltern im eigenen Analysator.
  47. </para>
  48. <para>
  49. Hier ist ein Beispiel für einen eigenen Analysator, welcher Wörter mit Ziffern als
  50. Begriffe akzeptiert:
  51. <example id="zend.search.lucene.extending.analysis.example-1">
  52. <title>Eigener Textanalysator</title>
  53. <programlisting language="php"><![CDATA[
  54. /**
  55. * Hier ist ein eigener Textanalysator, der Worte mit Ziffern
  56. * als einen Begriff behandelt
  57. */
  58. class My_Analyzer extends Zend_Search_Lucene_Analysis_Analyzer_Common
  59. {
  60. private $_position;
  61. /**
  62. * Setzt den Token Stream zurück
  63. */
  64. public function reset()
  65. {
  66. $this->_position = 0;
  67. }
  68. /**
  69. * Tokenization stream API
  70. * Get next token
  71. * Returns null at the end of stream
  72. *
  73. * @return Zend_Search_Lucene_Analysis_Token|null
  74. */
  75. public function nextToken()
  76. {
  77. if ($this->_input === null) {
  78. return null;
  79. }
  80. while ($this->_position < strlen($this->_input)) {
  81. // skip white space
  82. while ($this->_position < strlen($this->_input) &&
  83. !ctype_alnum( $this->_input[$this->_position] )) {
  84. $this->_position++;
  85. }
  86. $termStartPosition = $this->_position;
  87. // read token
  88. while ($this->_position < strlen($this->_input) &&
  89. ctype_alnum( $this->_input[$this->_position] )) {
  90. $this->_position++;
  91. }
  92. // Empty token, end of stream.
  93. if ($this->_position == $termStartPosition) {
  94. return null;
  95. }
  96. $token = new Zend_Search_Lucene_Analysis_Token(
  97. substr($this->_input,
  98. $termStartPosition,
  99. $this->_position -
  100. $termStartPosition),
  101. $termStartPosition,
  102. $this->_position);
  103. $token = $this->normalize($token);
  104. if ($token !== null) {
  105. return $token;
  106. }
  107. // Continue if token is skipped
  108. }
  109. return null;
  110. }
  111. }
  112. Zend_Search_Lucene_Analysis_Analyzer::setDefault(
  113. new My_Analyzer());
  114. ]]></programlisting>
  115. </example>
  116. </para>
  117. </sect2>
  118. <sect2 id="zend.search.lucene.extending.filters">
  119. <title>Filtern von Tokens</title>
  120. <para>
  121. Der <classname>Zend_Search_Lucene_Analysis_Analyzer_Common</classname> Analisator bietet
  122. auch einen Mechanismus zum Filtern von Tokens.
  123. </para>
  124. <para>
  125. Die <classname>Zend_Search_Lucene_Analysis_TokenFilter</classname> Klasse bietet ein
  126. abstraktes Interface für solche Filter. Eigene Filter sollten diese Klasse direkt oder
  127. indirekt erweitern.
  128. </para>
  129. <para>
  130. Alle eigenen Filter müssen die <methodname>normalize()</methodname> Methode
  131. implementieren, welche den Eingabe Token verändern oder signalisieren, dass der Token
  132. übersprungen werden sollte.
  133. </para>
  134. <para>
  135. Es gibt bereits drei Filter die im Analyse Unterpaket definierte sind:
  136. <itemizedlist>
  137. <listitem>
  138. <para>
  139. <classname>Zend_Search_Lucene_Analysis_TokenFilter_LowerCase</classname>
  140. </para>
  141. </listitem>
  142. <listitem>
  143. <para>
  144. <classname>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</classname>
  145. </para>
  146. </listitem>
  147. <listitem>
  148. <para>
  149. <classname>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</classname>
  150. </para>
  151. </listitem>
  152. </itemizedlist>
  153. </para>
  154. <para>
  155. Der <code>LowerCase</code> Filter wird bereits standardmäßig für den
  156. <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</classname>
  157. Analysator verwendet.
  158. </para>
  159. <para>
  160. Die <code>ShortWords</code> und <code>StopWords</code> Filter können mit bereits
  161. definierten oder eigenen Analysatoren wie folgt verwendet werden:
  162. </para>
  163. <programlisting language="php"><![CDATA[
  164. $stopWords = array('a', 'an', 'at', 'the', 'and', 'or', 'is', 'am');
  165. $stopWordsFilter =
  166. new Zend_Search_Lucene_Analysis_TokenFilter_StopWords($stopWords);
  167. $analyzer =
  168. new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
  169. $analyzer->addFilter($stopWordsFilter);
  170. Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
  171. ]]></programlisting>
  172. <programlisting language="php"><![CDATA[
  173. $shortWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_ShortWords();
  174. $analyzer =
  175. new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
  176. $analyzer->addFilter($shortWordsFilter);
  177. Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
  178. ]]></programlisting>
  179. <para>
  180. Der <classname>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</classname> Konstruktor
  181. nimmt ein Array mit Stopwörtern als Eingabe entgegen. Aber Stopwörter können auch aus
  182. einer Datei geladen werden:
  183. </para>
  184. <programlisting language="php"><![CDATA[
  185. $stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords();
  186. $stopWordsFilter->loadFromFile($my_stopwords_file);
  187. $analyzer =
  188. new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
  189. $analyzer->addFilter($stopWordsFilter);
  190. Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
  191. ]]></programlisting>
  192. <para>
  193. Die Datei sollte eine normale Textdatei mit einem Wort pro Zeile sein. Das '#' Zeichen
  194. markiert eine Zeile als Kommentar.
  195. </para>
  196. <para>
  197. Der <classname>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</classname>
  198. Konstruktor hat ein optionales Argument. Es ist das Limit für die Wortlänge, der
  199. standardmäßig 2 ist.
  200. </para>
  201. </sect2>
  202. <sect2 id="zend.search.lucene.extending.scoring">
  203. <title>Algorithmen für Punktwertermittlung</title>
  204. <para>
  205. Der Punktwert einer Abfrage <literal>q</literal> für das Dokument <literal>d</literal>
  206. ist wie folgt definiert:
  207. </para>
  208. <para>
  209. <code>score(q,d) = sum( tf(t in d) * idf(t) * getBoost(t.field in d) *
  210. lengthNorm(t.field in d) ) * coord(q,d) * queryNorm(q)</code>
  211. </para>
  212. <para>
  213. tf(t in d) - <methodname>Zend_Search_Lucene_Search_Similarity::tf($freq)</methodname> -
  214. ein Punktwertfaktor, der auf der Häufigkeit des Begriffes oder der Phrase innerhalb des
  215. Dokuments basiert.
  216. </para>
  217. <para>
  218. idf(t) -
  219. <methodname>Zend_Search_Lucene_Search_Similarity::idf($input, $reader)</methodname>
  220. - ein Punktwertfaktor für einen einfachen Begriff mit dem spezifischen Index.
  221. </para>
  222. <para>
  223. getBoost(t.field in d) - der Verstärkungsfaktor für das Begriffsfeld.
  224. </para>
  225. <para>
  226. lengthNorm($term) - der Normalisierungswert für ein Feld, der die Gesamtzahl der
  227. Begriffe innerhalb eines Fields enthält. Dieser Wert wird im Index abgelegt. Diese Wert
  228. werden zusammen mit dem Verstärkungsfaktor im Index abgelegt und vom Suchcode für
  229. alle Treffer eines Feldes zu Punktwerten multipliziert.
  230. </para>
  231. <para>
  232. Treffer in längeren Feldern sind weniger präzise, so dass Implementierungen dieser
  233. Methode normalerweise kleinere Werte zurückgeben, wenn numTokens groß ist, und größere
  234. Werte, wenn numTokens klein ist.
  235. </para>
  236. <para>
  237. coord(q,d) - <methodname>Zend_Search_Lucene_Search_Similarity::coord($overlap,
  238. $maxOverlap)</methodname> - ein Punktwertfaktor, der auf dem Anteil aller
  239. Abfragebegriffe basiert, die ein Dokument enthält.
  240. </para>
  241. <para>
  242. Das Vorhandensein eines grossen Teils der Abfragebegriffe gibt einen besseren Treffer
  243. für die Abfrage an, so dass Implementierungen dieser Methode normalerweise größere
  244. Werte zurückgeben, wenn das Verhältnis zwischen diesen Parametern groß ist, und kleinere
  245. Werte, wenn es klein ist.
  246. </para>
  247. <para>
  248. queryNorm(q) - der Normalisierungswert für eine Abfrage, welcher die Summe der
  249. quadrierten Gewichtungen jedes Begriffes eine Abfrage enthält. Dieser Wert wird für das
  250. Gewicht jedes Abfragebegriffes multipliziert.
  251. term.
  252. </para>
  253. <para>
  254. Dieses wirkt sich nicht auf die Reihenfolge ist, versucht aber, die Punktwerte
  255. für verschiedenen Abfragen vergleichbar zu machen.
  256. </para>
  257. <para>
  258. Der Algorithmen für die Punktwertermittlung kann durch die Definition einer eigenen
  259. Ähnlichkeitsklasse angepasst werden. Hierfür muss die
  260. <classname>Zend_Search_Lucene_Search_Similarity</classname> Klasse wie unten angegeben
  261. erweitert und anschließend die
  262. <methodname>Zend_Search_Lucene_Search_Similarity::setDefault($similarity);</methodname>
  263. Methode verwendet werden um Sie als Standard zu setzen.
  264. </para>
  265. <programlisting language="php"><![CDATA[
  266. class MySimilarity extends Zend_Search_Lucene_Search_Similarity {
  267. public function lengthNorm($fieldName, $numTerms) {
  268. return 1.0/sqrt($numTerms);
  269. }
  270. public function queryNorm($sumOfSquaredWeights) {
  271. return 1.0/sqrt($sumOfSquaredWeights);
  272. }
  273. public function tf($freq) {
  274. return sqrt($freq);
  275. }
  276. /**
  277. * Es wird jetzt nicht verwendet. Berechnet den Wert eines Treffers
  278. * für eine ungenauen Phrasenanfrage.
  279. */
  280. public function sloppyFreq($distance) {
  281. return 1.0;
  282. }
  283. public function idfFreq($docFreq, $numDocs) {
  284. return log($numDocs/(float)($docFreq+1)) + 1.0;
  285. }
  286. public function coord($overlap, $maxOverlap) {
  287. return $overlap/(float)$maxOverlap;
  288. }
  289. }
  290. $mySimilarity = new MySimilarity();
  291. Zend_Search_Lucene_Search_Similarity::setDefault($mySimilarity);
  292. ]]></programlisting>
  293. </sect2>
  294. <sect2 id="zend.search.lucene.extending.storage">
  295. <title>Storage Container</title>
  296. <para>
  297. Die abstrakte Klasse <classname>Zend_Search_Lucene_Storage_Directory</classname>
  298. definiert Funktionalitäten für Verzeichnisse.
  299. </para>
  300. <para>
  301. Der <classname>Zend_Search_Lucene</classname> Konstruktur verwendet als Eingabe entweder
  302. einen String oder ein <classname>Zend_Search_Lucene_Storage_Directory</classname>
  303. Objekt.
  304. </para>
  305. <para>
  306. Die <classname>Zend_Search_Lucene_Storage_Directory_Filesystem</classname> Klasse
  307. implementiert Verzeichnisfunktionalitäten für ein Dateisystem.
  308. </para>
  309. <para>
  310. Wenn ein String als Eingabe für den <classname>Zend_Search_Lucene</classname>
  311. Konstruktur verwendet wird, behandelt der Indexleser (das <classname>Zend_Search_Lucene
  312. Objekt</classname>) es wie einen Dateipfad und instanziiert das
  313. <classname>Zend_Search_Lucene_Storage_Directory_Filesystem</classname> Objekt.
  314. </para>
  315. <para>
  316. Du kannst deinen eigenen Verzeichnisimplementation durch die Erweiterung der
  317. <classname>Zend_Search_Lucene_Storage_Directory</classname> Klasse definieren.
  318. </para>
  319. <para>
  320. <classname>Zend_Search_Lucene_Storage_Directory</classname> Methoden:
  321. </para>
  322. <programlisting language="php"><![CDATA[
  323. abstract class Zend_Search_Lucene_Storage_Directory {
  324. /**
  325. * Schließt den Speicher
  326. *
  327. * @return void
  328. */
  329. abstract function close();
  330. /**
  331. * Erstellt im Verzeichnis eine neue, leere Datei mit dem übergebenen Dateinamen $filename.
  332. *
  333. * @param string $name
  334. * @return void
  335. */
  336. abstract function createFile($filename);
  337. /**
  338. * Entfernt eine vorhande Datei $filename aus dem Verzeichnis.
  339. *
  340. * @param string $filename
  341. * @return void
  342. */
  343. abstract function deleteFile($filename);
  344. /**
  345. * Gibt true zurück, wenn eine Datei mit dem übergebenen Dateinamen $filename existiert
  346. *
  347. * @param string $filename
  348. * @return boolean
  349. */
  350. abstract function fileExists($filename);
  351. /**
  352. * Gibt die länge eine Datei $filename im Verzeichnis zurück
  353. *
  354. * @param string $filename
  355. * @return integer
  356. */
  357. abstract function fileLength($filename);
  358. /**
  359. * Gibt den UNIX Zeitstempel für die letzte Änderung der Datei $filename zurück.
  360. *
  361. * @param string $filename
  362. * @return integer
  363. */
  364. abstract function fileModified($filename);
  365. /**
  366. * Benennt eine vorhandene Datei im Verzeichnis um.
  367. *
  368. * @param string $from
  369. * @param string $to
  370. * @return void
  371. */
  372. abstract function renameFile($from, $to);
  373. /**
  374. * Ändert die Änderungstzeit der Datei $filename auf jetzt um
  375. *
  376. * @param string $filename
  377. * @return void
  378. */
  379. abstract function touchFile($filename);
  380. /**
  381. * Gibt ein Zend_Search_Lucene_Storage_File Objekt für den^
  382. * Dateinamen $filename aus dem Verzeichnis zurück.
  383. *
  384. * @param string $filename
  385. * @return Zend_Search_Lucene_Storage_File
  386. */
  387. abstract function getFileObject($filename);
  388. }
  389. ]]></programlisting>
  390. <para>
  391. Die <methodname>getFileObject($filename)</methodname> Methode einer
  392. <classname>Zend_Search_Lucene_Storage_Directory</classname> Instanz gibt ein
  393. <classname>Zend_Search_Lucene_Storage_File</classname> Objekt zurück.
  394. </para>
  395. <para>
  396. Die abstrakte Klasse <classname>Zend_Search_Lucene_Storage_File</classname>
  397. implementiert einfache Funktionen für Dateiabstraktion und das Lesen von Indexdateien.
  398. </para>
  399. <para>
  400. Es muß außerdem <classname>Zend_Search_Lucene_Storage_File</classname> für eine eigene
  401. Verzeichnisimplementation erweitert werden.
  402. </para>
  403. <para>
  404. Nur zwei Methoden der <classname>Zend_Search_Lucene_Storage_File</classname> Klasse
  405. müssen in der eigenen Implementation überschrieben werden:
  406. </para>
  407. <programlisting language="php"><![CDATA[
  408. class MyFile extends Zend_Search_Lucene_Storage_File {
  409. /**
  410. * Setzt den Indikator für die Dateiposition rückt den Dateizeiger
  411. * voran. Die neue Position, gemessen in Bytes vom Dateianfangm
  412. * wird erreicht durch das Hinzufügen eines Versatzes zu der
  413. * angegebenen Position. Dessen Werte sind wie folgt definiert:
  414. * SEEK_SET - Setze die Position auf den Versatz.
  415. * SEEK_CUR - Setze die Position auf die aktuelle Position plus Versatz.
  416. * SEEK_END - Setze die Position aufs Dateisende plus Versatz. (Um den
  417. * Zeiger auf eine Position vor dem Dateiende zu bewegen, übergebe einen
  418. * negativen Wert als Versatz.)
  419. * Bei Erfolg wird 0, andernfalls -1 zurückgegeben
  420. *
  421. * @param integer $offset
  422. * @param integer $whence
  423. * @return integer
  424. */
  425. public function seek($offset, $whence=SEEK_SET) {
  426. ...
  427. }
  428. /**
  429. * Lese $length Bytes aus der Datei und setze den Dateizeiger vor.
  430. *
  431. * @param integer $length
  432. * @return string
  433. */
  434. protected function _fread($length=1) {
  435. ...
  436. }
  437. }
  438. ]]></programlisting>
  439. </sect2>
  440. </sect1>