MultiReader.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:15k
源码类别:

搜索引擎

开发平台:

C#

  1. /*
  2.  * Copyright 2004 The Apache Software Foundation
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. using System;
  17. using Document = Lucene.Net.Documents.Document;
  18. using Field = Lucene.Net.Documents.Field;
  19. using Directory = Lucene.Net.Store.Directory;
  20. namespace Lucene.Net.Index
  21. {
  22. /// <summary>An IndexReader which reads multiple indexes, appending their content.
  23. /// 
  24. /// </summary>
  25. /// <version>  $Id: MultiReader.java 355181 2005-12-08 19:53:06Z cutting $
  26. /// </version>
  27. public class MultiReader : IndexReader
  28. {
  29. private IndexReader[] subReaders;
  30. private int[] starts; // 1st docno for each segment
  31. private System.Collections.Hashtable normsCache = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
  32. private int maxDoc = 0;
  33. private int numDocs = - 1;
  34. private bool hasDeletions = false;
  35. /// <summary> <p>Construct a MultiReader aggregating the named set of (sub)readers.
  36. /// Directory locking for delete, undeleteAll, and setNorm operations is
  37. /// left to the subreaders. </p>
  38. /// <p>Note that all subreaders are closed if this Multireader is closed.</p>
  39. /// </summary>
  40. /// <param name="subReaders">set of (sub)readers
  41. /// </param>
  42. /// <throws>  IOException </throws>
  43. public MultiReader(IndexReader[] subReaders):base(subReaders.Length == 0?null:subReaders[0].Directory())
  44. {
  45. Initialize(subReaders);
  46. }
  47. /// <summary>Construct reading the named set of readers. </summary>
  48. public /*internal*/ MultiReader(Directory directory, SegmentInfos sis, bool closeDirectory, IndexReader[] subReaders) : base(directory, sis, closeDirectory)
  49. {
  50. Initialize(subReaders);
  51. }
  52. private void  Initialize(IndexReader[] subReaders)
  53. {
  54. this.subReaders = subReaders;
  55. starts = new int[subReaders.Length + 1]; // build starts array
  56. for (int i = 0; i < subReaders.Length; i++)
  57. {
  58. starts[i] = maxDoc;
  59. maxDoc += subReaders[i].MaxDoc(); // compute maxDocs
  60. if (subReaders[i].HasDeletions())
  61. hasDeletions = true;
  62. }
  63. starts[subReaders.Length] = maxDoc;
  64. }
  65. /// <summary>Return an array of term frequency vectors for the specified document.
  66. /// The array contains a vector for each vectorized field in the document.
  67. /// Each vector vector contains term numbers and frequencies for all terms
  68. /// in a given vectorized field.
  69. /// If no such fields existed, the method returns null.
  70. /// </summary>
  71. public override TermFreqVector[] GetTermFreqVectors(int n)
  72. {
  73. int i = ReaderIndex(n); // find segment num
  74. return subReaders[i].GetTermFreqVectors(n - starts[i]); // dispatch to segment
  75. }
  76. public override TermFreqVector GetTermFreqVector(int n, System.String field)
  77. {
  78. int i = ReaderIndex(n); // find segment num
  79. return subReaders[i].GetTermFreqVector(n - starts[i], field);
  80. }
  81. public override int NumDocs()
  82. {
  83. lock (this)
  84. {
  85. if (numDocs == - 1)
  86. {
  87. // check cache
  88. int n = 0; // cache miss--recompute
  89. for (int i = 0; i < subReaders.Length; i++)
  90. n += subReaders[i].NumDocs(); // sum from readers
  91. numDocs = n;
  92. }
  93. return numDocs;
  94. }
  95. }
  96. public override int MaxDoc()
  97. {
  98. return maxDoc;
  99. }
  100. public override Document Document(int n)
  101. {
  102. int i = ReaderIndex(n); // find segment num
  103. return subReaders[i].Document(n - starts[i]); // dispatch to segment reader
  104. }
  105. public override bool IsDeleted(int n)
  106. {
  107. int i = ReaderIndex(n); // find segment num
  108. return subReaders[i].IsDeleted(n - starts[i]); // dispatch to segment reader
  109. }
  110. public override bool HasDeletions()
  111. {
  112. return hasDeletions;
  113. }
  114. protected internal override void  DoDelete(int n)
  115. {
  116. numDocs = - 1; // invalidate cache
  117. int i = ReaderIndex(n); // find segment num
  118. subReaders[i].Delete(n - starts[i]); // dispatch to segment reader
  119. hasDeletions = true;
  120. }
  121. protected internal override void  DoUndeleteAll()
  122. {
  123. for (int i = 0; i < subReaders.Length; i++)
  124. subReaders[i].UndeleteAll();
  125. hasDeletions = false;
  126. numDocs = - 1; // invalidate cache
  127. }
  128. private int ReaderIndex(int n)
  129. {
  130. // find reader for doc n:
  131. int lo = 0; // search starts array
  132. int hi = subReaders.Length - 1; // for first element less
  133. while (hi >= lo)
  134. {
  135. int mid = (lo + hi) >> 1;
  136. int midValue = starts[mid];
  137. if (n < midValue)
  138. hi = mid - 1;
  139. else if (n > midValue)
  140. lo = mid + 1;
  141. else
  142. {
  143. // found a match
  144. while (mid + 1 < subReaders.Length && starts[mid + 1] == midValue)
  145. {
  146. mid++; // scan to last match
  147. }
  148. return mid;
  149. }
  150. }
  151. return hi;
  152. }
  153. public override bool HasNorms(System.String field)
  154. {
  155. for (int i = 0; i < subReaders.Length; i++)
  156. {
  157. if (subReaders[i].HasNorms(field))
  158. return true;
  159. }
  160. return false;
  161. }
  162. private byte[] ones;
  163. private byte[] FakeNorms()
  164. {
  165. if (ones == null)
  166. ones = SegmentReader.CreateFakeNorms(MaxDoc());
  167. return ones;
  168. }
  169. public override byte[] Norms(System.String field)
  170. {
  171. lock (this)
  172. {
  173. byte[] bytes = (byte[]) normsCache[field];
  174. if (bytes != null)
  175. return bytes; // cache hit
  176. if (!HasNorms(field))
  177. return FakeNorms();
  178. bytes = new byte[MaxDoc()];
  179. for (int i = 0; i < subReaders.Length; i++)
  180. subReaders[i].Norms(field, bytes, starts[i]);
  181. normsCache[field] = bytes; // update cache
  182. return bytes;
  183. }
  184. }
  185. public override void  Norms(System.String field, byte[] result, int offset)
  186. {
  187. lock (this)
  188. {
  189. byte[] bytes = (byte[]) normsCache[field];
  190. if (bytes == null && !HasNorms(field))
  191. bytes = FakeNorms();
  192. if (bytes != null)
  193.     // cache hit
  194. Array.Copy(bytes, 0, result, offset, MaxDoc());
  195. for (int i = 0; i < subReaders.Length; i++)
  196.     // read from segments
  197. subReaders[i].Norms(field, result, offset + starts[i]);
  198. }
  199. }
  200. protected internal override void  DoSetNorm(int n, System.String field, byte value_Renamed)
  201. {
  202. normsCache.Remove(field); // clear cache
  203. int i = ReaderIndex(n); // find segment num
  204. subReaders[i].SetNorm(n - starts[i], field, value_Renamed); // dispatch
  205. }
  206. public override TermEnum Terms()
  207. {
  208. return new MultiTermEnum(subReaders, starts, null);
  209. }
  210. public override TermEnum Terms(Term term)
  211. {
  212. return new MultiTermEnum(subReaders, starts, term);
  213. }
  214. public override int DocFreq(Term t)
  215. {
  216. int total = 0; // sum freqs in segments
  217. for (int i = 0; i < subReaders.Length; i++)
  218. total += subReaders[i].DocFreq(t);
  219. return total;
  220. }
  221. public override TermDocs TermDocs()
  222. {
  223. return new MultiTermDocs(subReaders, starts);
  224. }
  225. public override TermPositions TermPositions()
  226. {
  227. return new MultiTermPositions(subReaders, starts);
  228. }
  229. protected internal override void  DoCommit()
  230. {
  231. for (int i = 0; i < subReaders.Length; i++)
  232. subReaders[i].Commit();
  233. }
  234. protected internal override void  DoClose()
  235. {
  236. lock (this)
  237. {
  238. for (int i = 0; i < subReaders.Length; i++)
  239. subReaders[i].Close();
  240. }
  241. }
  242. /// <seealso cref="IndexReader.GetFieldNames()">
  243. /// </seealso>
  244. public override System.Collections.ICollection GetFieldNames()
  245. {
  246. // maintain a unique set of field names
  247. System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
  248. for (int i = 0; i < subReaders.Length; i++)
  249. {
  250. IndexReader reader = subReaders[i];
  251. System.Collections.ICollection names = reader.GetFieldNames();
  252.                 for (System.Collections.IEnumerator iterator = names.GetEnumerator(); iterator.MoveNext(); )
  253.                 {
  254.                     System.Collections.DictionaryEntry fi = (System.Collections.DictionaryEntry) iterator.Current;
  255.                     System.String s = fi.Key.ToString();
  256.                     if (fieldSet.ContainsKey(s) == false)
  257.                     {
  258.                         fieldSet.Add(s, s);
  259.                     }
  260.                 }
  261.             }
  262. return fieldSet;
  263. }
  264. /// <seealso cref="IndexReader.GetFieldNames(boolean)">
  265. /// </seealso>
  266. public override System.Collections.ICollection GetFieldNames(bool indexed)
  267. {
  268. // maintain a unique set of field names
  269. System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
  270. for (int i = 0; i < subReaders.Length; i++)
  271. {
  272. IndexReader reader = subReaders[i];
  273. System.Collections.ICollection names = reader.GetFieldNames(indexed);
  274.                 for (System.Collections.IEnumerator iterator = names.GetEnumerator(); iterator.MoveNext(); )
  275.                 {
  276.                     System.Collections.DictionaryEntry fi = (System.Collections.DictionaryEntry) iterator.Current;
  277.                     System.String s = fi.Key.ToString();
  278.                     if (fieldSet.ContainsKey(s) == false)
  279.                     {
  280.                         fieldSet.Add(s, s);
  281.                     }
  282.                 }
  283.             }
  284. return fieldSet;
  285. }
  286. public override System.Collections.ICollection GetIndexedFieldNames(Field.TermVector tvSpec)
  287. {
  288. // maintain a unique set of field names
  289. System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
  290. for (int i = 0; i < subReaders.Length; i++)
  291. {
  292. IndexReader reader = subReaders[i];
  293. System.Collections.ICollection names = reader.GetIndexedFieldNames(tvSpec);
  294.                 foreach (object item in names)
  295.                 {
  296.                     if (fieldSet.ContainsKey(item) == false)
  297.                     {
  298.                         fieldSet.Add(item, item);
  299.                     }
  300.                 }
  301.             }
  302. return fieldSet;
  303. }
  304. /// <seealso cref="IndexReader.GetFieldNames(IndexReader.FieldOption)">
  305. /// </seealso>
  306. public override System.Collections.ICollection GetFieldNames(IndexReader.FieldOption fieldNames)
  307. {
  308. // maintain a unique set of field names
  309. System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
  310. for (int i = 0; i < subReaders.Length; i++)
  311. {
  312. IndexReader reader = subReaders[i];
  313. System.Collections.ICollection names = reader.GetFieldNames(fieldNames);
  314.                 foreach (object item in names)
  315.                 {
  316.                     if (fieldSet.ContainsKey(item) == false)
  317.                     {
  318.                         fieldSet.Add(item, item);
  319.                     }
  320.                 }
  321.             }
  322. return fieldSet;
  323. }
  324. }
  325. class MultiTermEnum : TermEnum
  326. {
  327. private SegmentMergeQueue queue;
  328. private Term term;
  329. private int docFreq;
  330. public MultiTermEnum(IndexReader[] readers, int[] starts, Term t)
  331. {
  332. queue = new SegmentMergeQueue(readers.Length);
  333. for (int i = 0; i < readers.Length; i++)
  334. {
  335. IndexReader reader = readers[i];
  336. TermEnum termEnum;
  337. if (t != null)
  338. {
  339. termEnum = reader.Terms(t);
  340. }
  341. else
  342. termEnum = reader.Terms();
  343. SegmentMergeInfo smi = new SegmentMergeInfo(starts[i], termEnum, reader);
  344. if (t == null?smi.Next():termEnum.Term() != null)
  345. queue.Put(smi);
  346. // initialize queue
  347. else
  348. smi.Close();
  349. }
  350. if (t != null && queue.Size() > 0)
  351. {
  352. Next();
  353. }
  354. }
  355. public override bool Next()
  356. {
  357. SegmentMergeInfo top = (SegmentMergeInfo) queue.Top();
  358. if (top == null)
  359. {
  360. term = null;
  361. return false;
  362. }
  363. term = top.term;
  364. docFreq = 0;
  365. while (top != null && term.CompareTo(top.term) == 0)
  366. {
  367. queue.Pop();
  368. docFreq += top.termEnum.DocFreq(); // increment freq
  369. if (top.Next())
  370. queue.Put(top);
  371. // restore queue
  372. else
  373. top.Close(); // done with a segment
  374. top = (SegmentMergeInfo) queue.Top();
  375. }
  376. return true;
  377. }
  378. public override Term Term()
  379. {
  380. return term;
  381. }
  382. public override int DocFreq()
  383. {
  384. return docFreq;
  385. }
  386. public override void  Close()
  387. {
  388. queue.Close();
  389. }
  390. }
  391. class MultiTermDocs : TermDocs
  392. {
  393. protected internal IndexReader[] readers;
  394. protected internal int[] starts;
  395. protected internal Term term;
  396. protected internal int base_Renamed = 0;
  397. protected internal int pointer = 0;
  398. private TermDocs[] readerTermDocs;
  399. protected internal TermDocs current; // == readerTermDocs[pointer]
  400. public MultiTermDocs(IndexReader[] r, int[] s)
  401. {
  402. readers = r;
  403. starts = s;
  404. readerTermDocs = new TermDocs[r.Length];
  405. }
  406. public virtual int Doc()
  407. {
  408. return base_Renamed + current.Doc();
  409. }
  410. public virtual int Freq()
  411. {
  412. return current.Freq();
  413. }
  414. public virtual void  Seek(Term term)
  415. {
  416. this.term = term;
  417. this.base_Renamed = 0;
  418. this.pointer = 0;
  419. this.current = null;
  420. }
  421. public virtual void  Seek(TermEnum termEnum)
  422. {
  423. Seek(termEnum.Term());
  424. }
  425. public virtual bool Next()
  426. {
  427. if (current != null && current.Next())
  428. {
  429. return true;
  430. }
  431. else if (pointer < readers.Length)
  432. {
  433. base_Renamed = starts[pointer];
  434. current = TermDocs(pointer++);
  435. return Next();
  436. }
  437. else
  438. return false;
  439. }
  440. /// <summary>Optimized implementation. </summary>
  441. public virtual int Read(int[] docs, int[] freqs)
  442. {
  443. while (true)
  444. {
  445. while (current == null)
  446. {
  447. if (pointer < readers.Length)
  448. {
  449. // try next segment
  450. base_Renamed = starts[pointer];
  451. current = TermDocs(pointer++);
  452. }
  453. else
  454. {
  455. return 0;
  456. }
  457. }
  458. int end = current.Read(docs, freqs);
  459. if (end == 0)
  460. {
  461. // none left in segment
  462. current = null;
  463. }
  464. else
  465. {
  466. // got some
  467. int b = base_Renamed; // adjust doc numbers
  468. for (int i = 0; i < end; i++)
  469. docs[i] += b;
  470. return end;
  471. }
  472. }
  473. }
  474. /// <summary>As yet unoptimized implementation. </summary>
  475. public virtual bool SkipTo(int target)
  476. {
  477. do 
  478. {
  479. if (!Next())
  480. return false;
  481. }
  482. while (target > Doc());
  483. return true;
  484. }
  485. private TermDocs TermDocs(int i)
  486. {
  487. if (term == null)
  488. return null;
  489. TermDocs result = readerTermDocs[i];
  490. if (result == null)
  491. result = readerTermDocs[i] = TermDocs(readers[i]);
  492. result.Seek(term);
  493. return result;
  494. }
  495. protected internal virtual TermDocs TermDocs(IndexReader reader)
  496. {
  497. return reader.TermDocs();
  498. }
  499. public virtual void  Close()
  500. {
  501. for (int i = 0; i < readerTermDocs.Length; i++)
  502. {
  503. if (readerTermDocs[i] != null)
  504. readerTermDocs[i].Close();
  505. }
  506. }
  507. }
  508. class MultiTermPositions : MultiTermDocs, TermPositions
  509. {
  510. public MultiTermPositions(IndexReader[] r, int[] s):base(r, s)
  511. {
  512. }
  513. protected internal override TermDocs TermDocs(IndexReader reader)
  514. {
  515. return (TermDocs) reader.TermPositions();
  516. }
  517. public virtual int NextPosition()
  518. {
  519. return ((TermPositions) current).NextPosition();
  520. }
  521. }
  522. }