/src/3rdparty/clucene/src/CLucene/search/Hits.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 174 lines · 120 code · 34 blank · 20 comment · 20 complexity · b136a3fcfd0241f2abe3f26ebda38074 MD5 · raw file

  1. /*------------------------------------------------------------------------------
  2. * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
  3. *
  4. * Distributable under the terms of either the Apache License (Version 2.0) or
  5. * the GNU Lesser General Public License, as specified in the COPYING file.
  6. ------------------------------------------------------------------------------*/
  7. #include "CLucene/StdHeader.h"
  8. #include "SearchHeader.h"
  9. #include "CLucene/document/Document.h"
  10. #include "CLucene/index/IndexReader.h"
  11. #include "Filter.h"
  12. #include "CLucene/search/SearchHeader.h"
  13. CL_NS_USE(document)
  14. CL_NS_USE(util)
  15. CL_NS_USE(index)
  16. CL_NS_DEF(search)
  17. HitDoc::HitDoc(const qreal s, const int32_t i)
  18. {
  19. //Func - Constructor
  20. //Pre - true
  21. //Post - The instance has been created
  22. next = NULL;
  23. prev = NULL;
  24. doc = NULL;
  25. score = s;
  26. id = i;
  27. }
  28. HitDoc::~HitDoc(){
  29. //Func - Destructor
  30. //Pre - true
  31. //Post - The instance has been destroyed
  32. _CLDELETE(doc);
  33. }
  34. Hits::Hits(Searcher* s, Query* q, Filter* f, const Sort* _sort):
  35. query(q), searcher(s), filter(f), sort(_sort)
  36. {
  37. //Func - Constructor
  38. //Pre - s contains a valid reference to a searcher s
  39. // q contains a valid reference to a Query
  40. // f is NULL or contains a pointer to a filter
  41. //Post - The instance has been created
  42. _length = 0;
  43. first = NULL;
  44. last = NULL;
  45. numDocs = 0;
  46. maxDocs = 200;
  47. //retrieve 100 initially
  48. getMoreDocs(50);
  49. }
  50. Hits::~Hits(){
  51. }
  52. int32_t Hits::length() const {
  53. return _length;
  54. }
  55. Document& Hits::doc(const int32_t n){
  56. HitDoc* hitDoc = getHitDoc(n);
  57. // Update LRU cache of documents
  58. remove(hitDoc); // remove from list, if there
  59. addToFront(hitDoc); // add to front of list
  60. if (numDocs > maxDocs) { // if cache is full
  61. HitDoc* oldLast = last;
  62. remove(last); // flush last
  63. _CLDELETE( oldLast->doc );
  64. oldLast->doc = NULL;
  65. }
  66. if (hitDoc->doc == NULL){
  67. hitDoc->doc = _CLNEW Document;
  68. searcher->doc(hitDoc->id, hitDoc->doc); // cache miss: read document
  69. }
  70. return *hitDoc->doc;
  71. }
  72. int32_t Hits::id (const int32_t n){
  73. return getHitDoc(n)->id;
  74. }
  75. qreal Hits::score(const int32_t n){
  76. return getHitDoc(n)->score;
  77. }
  78. void Hits::getMoreDocs(const size_t m){
  79. size_t _min = m;
  80. {
  81. size_t nHits = hitDocs.size();
  82. if ( nHits > _min)
  83. _min = nHits;
  84. }
  85. size_t n = _min * 2; // double # retrieved
  86. TopDocs* topDocs = NULL;
  87. if ( sort==NULL )
  88. topDocs = (TopDocs*)((Searchable*)searcher)->_search(query, filter, n);
  89. else
  90. topDocs = (TopDocs*)((Searchable*)searcher)->_search(query, filter, n, sort);
  91. _length = topDocs->totalHits;
  92. ScoreDoc* scoreDocs = topDocs->scoreDocs;
  93. int32_t scoreDocsLength = topDocs->scoreDocsLength;
  94. qreal scoreNorm = 1.0f;
  95. //Check that scoreDocs is a valid pointer before using it
  96. if (scoreDocs != NULL){
  97. if (_length > 0 && scoreDocs[0].score > 1.0f){
  98. scoreNorm = 1.0f / scoreDocs[0].score;
  99. }
  100. int32_t end = scoreDocsLength < _length ? scoreDocsLength : _length;
  101. for (int32_t i = hitDocs.size(); i < end; i++) {
  102. hitDocs.push_back(_CLNEW HitDoc(scoreDocs[i].score*scoreNorm, scoreDocs[i].doc));
  103. }
  104. }
  105. _CLDELETE(topDocs);
  106. }
  107. HitDoc* Hits::getHitDoc(const size_t n){
  108. if (n >= _length){
  109. TCHAR buf[100];
  110. _sntprintf(buf, 100,_T("Not a valid hit number: %d"),n);
  111. _CLTHROWT(CL_ERR_IndexOutOfBounds, buf );
  112. }
  113. if (n >= hitDocs.size())
  114. getMoreDocs(n);
  115. return hitDocs[n];
  116. }
  117. void Hits::addToFront(HitDoc* hitDoc) { // insert at front of cache
  118. if (first == NULL)
  119. last = hitDoc;
  120. else
  121. first->prev = hitDoc;
  122. hitDoc->next = first;
  123. first = hitDoc;
  124. hitDoc->prev = NULL;
  125. numDocs++;
  126. }
  127. void Hits::remove(const HitDoc* hitDoc) { // remove from cache
  128. if (hitDoc->doc == NULL) // it's not in the list
  129. return; // abort
  130. if (hitDoc->next == NULL)
  131. last = hitDoc->prev;
  132. else
  133. hitDoc->next->prev = hitDoc->prev;
  134. if (hitDoc->prev == NULL)
  135. first = hitDoc->next;
  136. else
  137. hitDoc->prev->next = hitDoc->next;
  138. numDocs--;
  139. }
  140. CL_NS_END