~ubuntu-branches/ubuntu/raring/clucene-core/raring-proposed

« back to all changes in this revision

Viewing changes to src/core/CLucene/search/IndexSearcher.cpp

  • Committer: Package Import Robot
  • Author(s): Fathi Boudra
  • Date: 2012-08-11 09:33:38 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20120811093338-fgrx41ftqew3qt6a
Tags: 2.3.3.4-1
* New upstream release (Closes: #661703).
* Convert package to multiarch.
* Drop obsolete patches:
  - 01_add_missing_include_bug505667.diff
  - 02_posixness_fix_bug530308.diff
* Add patches:
  - Fixing_ZLIB_configuration_in_shared_CMakeLists.patch
  - Fix-pkgconfig-file-by-adding-clucene-shared-library.patch
  - Install-contribs-lib.patch
  - multiarch.patch
* Update debian/compat: bump to 8.
* Update debian/control:
  - update build dependencies (add cmake, libboost-dev and libz-dev).
  - bump Standards-Version to 3.9.3.
  - rename packages due to ABI bump: libclucene0ldbl -> libclucene-core1.
  - add libclucene-contribs1 package.
* Update debian/rules:
  - rewrite to use CMake.
  - add multiarch support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/_ApiHeader.h"
 
8
#include "IndexSearcher.h"
 
9
 
 
10
#include "SearchHeader.h"
 
11
#include "Scorer.h"
 
12
#include "_HitQueue.h"
 
13
#include "Query.h"
 
14
#include "Filter.h"
 
15
#include "_FieldDocSortedHitQueue.h"
 
16
#include "CLucene/store/Directory.h"
 
17
#include "CLucene/document/Document.h"
 
18
#include "CLucene/index/IndexReader.h"
 
19
#include "CLucene/index/Term.h"
 
20
#include "CLucene/util/BitSet.h"
 
21
#include "FieldSortedHitQueue.h"
 
22
#include "Explanation.h"
 
23
 
 
24
CL_NS_USE(index)
 
25
CL_NS_USE(util)
 
26
CL_NS_USE(document)
 
27
 
 
28
CL_NS_DEF(search)
 
29
 
 
30
        class SimpleTopDocsCollector:public HitCollector{ 
 
31
        private:
 
32
                float_t minScore;
 
33
                const CL_NS(util)::BitSet* bits;
 
34
                HitQueue* hq;
 
35
                size_t nDocs;
 
36
                int32_t* totalHits;
 
37
        public:
 
38
                SimpleTopDocsCollector(const CL_NS(util)::BitSet* bs, HitQueue* hitQueue, int32_t* totalhits, size_t ndocs, const float_t ms=-1.0f):
 
39
                minScore(ms),
 
40
                bits(bs),
 
41
                hq(hitQueue),
 
42
                nDocs(ndocs),
 
43
                totalHits(totalhits)
 
44
        {
 
45
        }
 
46
                ~SimpleTopDocsCollector(){}
 
47
                void collect(const int32_t doc, const float_t score){
 
48
                if (score > 0.0f &&                       // ignore zeroed buckets
 
49
                        (bits==NULL || bits->get(doc))) {         // skip docs not in bits
 
50
                        ++totalHits[0];
 
51
                        if (hq->size() < nDocs || (minScore==-1.0f || score >= minScore)) {
 
52
                                ScoreDoc sd = {doc, score};
 
53
                                hq->insert(sd);   // update hit queue
 
54
                                if ( minScore != -1.0f )
 
55
                                        minScore = hq->top().score; // maintain minScore
 
56
                        }
 
57
                }
 
58
        }
 
59
        };
 
60
 
 
61
        class SortedTopDocsCollector:public HitCollector{ 
 
62
        private:
 
63
                const CL_NS(util)::BitSet* bits;
 
64
                FieldSortedHitQueue* hq;
 
65
                size_t nDocs;
 
66
                int32_t* totalHits;
 
67
        public:
 
68
                SortedTopDocsCollector(const CL_NS(util)::BitSet* bs, FieldSortedHitQueue* hitQueue, int32_t* totalhits, size_t _nDocs):
 
69
                bits(bs),
 
70
                hq(hitQueue),
 
71
                nDocs(_nDocs),
 
72
                totalHits(totalhits)
 
73
        {
 
74
        }
 
75
                ~SortedTopDocsCollector(){
 
76
                }
 
77
                void collect(const int32_t doc, const float_t score){
 
78
                if (score > 0.0f &&                       // ignore zeroed buckets
 
79
                        (bits==NULL || bits->get(doc))) {         // skip docs not in bits
 
80
                        ++totalHits[0];
 
81
                        FieldDoc* fd = _CLNEW FieldDoc(doc, score); //todo: see jlucene way... with fields def???
 
82
                        if ( !hq->insert(fd) )    // update hit queue
 
83
                                _CLDELETE(fd);
 
84
                }
 
85
        }
 
86
        };
 
87
 
 
88
        class SimpleFilteredCollector: public HitCollector{
 
89
        private:
 
90
                CL_NS(util)::BitSet* bits;
 
91
                HitCollector* results;
 
92
        public:
 
93
                SimpleFilteredCollector(CL_NS(util)::BitSet* bs, HitCollector* collector):
 
94
            bits(bs),
 
95
            results(collector)
 
96
        {
 
97
        }
 
98
                ~SimpleFilteredCollector(){
 
99
                }
 
100
        protected:
 
101
                void collect(const int32_t doc, const float_t score){
 
102
            if (bits->get(doc)) {                 // skip docs not in bits
 
103
                results->collect(doc, score);
 
104
            }
 
105
        }
 
106
        };
 
107
 
 
108
 
 
109
  IndexSearcher::IndexSearcher(const char* path){
 
110
  //Func - Constructor
 
111
  //       Creates a searcher searching the index in the named directory.  */
 
112
  //Pre  - path != NULL
 
113
  //Post - The instance has been created
 
114
 
 
115
      CND_PRECONDITION(path != NULL, "path is NULL");
 
116
 
 
117
      reader = IndexReader::open(path);
 
118
      readerOwner = true;
 
119
  }
 
120
  
 
121
  IndexSearcher::IndexSearcher(CL_NS(store)::Directory* directory){
 
122
  //Func - Constructor
 
123
  //       Creates a searcher searching the index in the specified directory.  */
 
124
  //Pre  - path != NULL
 
125
  //Post - The instance has been created
 
126
 
 
127
      CND_PRECONDITION(directory != NULL, "directory is NULL");
 
128
 
 
129
      reader = IndexReader::open(directory);
 
130
      readerOwner = true;
 
131
  }
 
132
 
 
133
  IndexSearcher::IndexSearcher(IndexReader* r){
 
134
  //Func - Constructor
 
135
  //       Creates a searcher searching the index with the provide IndexReader
 
136
  //Pre  - path != NULL
 
137
  //Post - The instance has been created
 
138
 
 
139
      reader      = r;
 
140
      readerOwner = false;
 
141
  }
 
142
 
 
143
  IndexSearcher::~IndexSearcher(){
 
144
  //Func - Destructor
 
145
  //Pre  - true
 
146
  //Post - The instance has been destroyed
 
147
 
 
148
          close();
 
149
  }
 
150
 
 
151
  void IndexSearcher::close(){
 
152
  //Func - Frees resources associated with this Searcher.
 
153
  //Pre  - true
 
154
  //Post - The resources associated have been freed
 
155
      if (readerOwner && reader){
 
156
          reader->close();
 
157
          _CLDELETE(reader);
 
158
      }
 
159
  }
 
160
 
 
161
  // inherit javadoc
 
162
  int32_t IndexSearcher::docFreq(const Term* term) const{
 
163
  //Func - 
 
164
  //Pre  - reader != NULL
 
165
  //Post -
 
166
 
 
167
      CND_PRECONDITION(reader != NULL, "reader is NULL");
 
168
 
 
169
      return reader->docFreq(term);
 
170
  }
 
171
 
 
172
  _CL_DEPRECATED( doc(i, document) ) CL_NS(document)::Document* IndexSearcher::doc(int32_t i){
 
173
        CL_NS(document)::Document* ret = _CLNEW CL_NS(document)::Document;
 
174
        if (!doc(i,ret) )
 
175
                _CLDELETE(ret);
 
176
        return ret;
 
177
  }
 
178
  
 
179
  // inherit javadoc
 
180
  bool IndexSearcher::doc(int32_t i, CL_NS(document)::Document& d) {
 
181
  //Func - Retrieves i-th document found
 
182
  //       For use by HitCollector implementations.
 
183
  //Pre  - reader != NULL
 
184
  //Post - The i-th document has been returned
 
185
 
 
186
      CND_PRECONDITION(reader != NULL, "reader is NULL");
 
187
 
 
188
      return reader->document(i,d);
 
189
  }
 
190
  bool IndexSearcher::doc(int32_t i, CL_NS(document)::Document* d) {
 
191
  //Func - Retrieves i-th document found
 
192
  //       For use by HitCollector implementations.
 
193
  //Pre  - reader != NULL
 
194
  //Post - The i-th document has been returned
 
195
 
 
196
      CND_PRECONDITION(reader != NULL, "reader is NULL");
 
197
 
 
198
      return reader->document(i,*d);
 
199
  }
 
200
 
 
201
  // inherit javadoc
 
202
  int32_t IndexSearcher::maxDoc() const {
 
203
  //Func - Return total number of documents including the ones marked deleted
 
204
  //Pre  - reader != NULL
 
205
  //Post - The total number of documents including the ones marked deleted 
 
206
  //       has been returned
 
207
 
 
208
      CND_PRECONDITION(reader != NULL, "reader is NULL");
 
209
 
 
210
      return reader->maxDoc();
 
211
  }
 
212
 
 
213
  //todo: find out why we are passing Query* and not Weight*, as Weight is being extracted anyway from Query*
 
214
  TopDocs* IndexSearcher::_search(Query* query, Filter* filter, const int32_t nDocs){
 
215
  //Func -
 
216
  //Pre  - reader != NULL
 
217
  //Post -
 
218
 
 
219
      CND_PRECONDITION(reader != NULL, "reader is NULL");
 
220
      CND_PRECONDITION(query != NULL, "query is NULL");
 
221
 
 
222
      Weight* weight = query->weight(this);
 
223
      Scorer* scorer = weight->scorer(reader);
 
224
      if (scorer == NULL) {
 
225
        Query* wq = weight->getQuery();
 
226
        if (wq != query)
 
227
          _CLLDELETE(wq);
 
228
        _CLLDELETE(weight);
 
229
          return _CLNEW TopDocs(0, NULL, 0);
 
230
      }
 
231
 
 
232
      BitSet* bits = filter != NULL ? filter->bits(reader) : NULL;
 
233
      HitQueue* hq = _CLNEW HitQueue(nDocs);
 
234
 
 
235
                  //Check hq has been allocated properly
 
236
                  CND_CONDITION(hq != NULL, "Could not allocate memory for HitQueue hq");
 
237
        
 
238
                  int32_t* totalHits = _CL_NEWARRAY(int32_t,1);
 
239
      totalHits[0] = 0;
 
240
 
 
241
      SimpleTopDocsCollector hitCol(bits,hq,totalHits,nDocs,0.0f);
 
242
      scorer->score( &hitCol );
 
243
      _CLDELETE(scorer);
 
244
 
 
245
      int32_t scoreDocsLength = hq->size();
 
246
 
 
247
                ScoreDoc* scoreDocs = new ScoreDoc[scoreDocsLength];
 
248
 
 
249
                for (int32_t i = scoreDocsLength-1; i >= 0; --i)          // put docs in array
 
250
                        scoreDocs[i] = hq->pop();
 
251
 
 
252
      int32_t totalHitsInt = totalHits[0];
 
253
 
 
254
      _CLDELETE(hq);
 
255
                  if ( bits != NULL && filter->shouldDeleteBitSet(bits) )
 
256
                                _CLDELETE(bits);
 
257
            _CLDELETE_ARRAY(totalHits);
 
258
                  Query* wq = weight->getQuery();
 
259
                  if ( query != wq ) //query was re-written
 
260
                          _CLLDELETE(wq);
 
261
                  _CLDELETE(weight);
 
262
 
 
263
      return _CLNEW TopDocs(totalHitsInt, scoreDocs, scoreDocsLength);
 
264
  }
 
265
 
 
266
  // inherit javadoc
 
267
  TopFieldDocs* IndexSearcher::_search(Query* query, Filter* filter, const int32_t nDocs,
 
268
         const Sort* sort) {
 
269
             
 
270
      CND_PRECONDITION(reader != NULL, "reader is NULL");
 
271
      CND_PRECONDITION(query != NULL, "query is NULL");
 
272
 
 
273
    Weight* weight = query->weight(this);
 
274
    Scorer* scorer = weight->scorer(reader);
 
275
    if (scorer == NULL){
 
276
                return _CLNEW TopFieldDocs(0, NULL, 0, NULL );
 
277
        }
 
278
 
 
279
    BitSet* bits = filter != NULL ? filter->bits(reader) : NULL;
 
280
    FieldSortedHitQueue hq(reader, sort->getSort(), nDocs);
 
281
    int32_t* totalHits = _CL_NEWARRAY(int32_t,1);
 
282
        totalHits[0]=0;
 
283
    
 
284
        SortedTopDocsCollector hitCol(bits,&hq,totalHits,nDocs);
 
285
        scorer->score(&hitCol);
 
286
    _CLLDELETE(scorer);
 
287
 
 
288
        int32_t hqLen = hq.size();
 
289
    FieldDoc** fieldDocs = _CL_NEWARRAY(FieldDoc*,hqLen);
 
290
        for (int32_t i = hqLen-1; i >= 0; --i){   // put docs in array
 
291
          fieldDocs[i] = hq.fillFields (hq.pop());
 
292
        }
 
293
 
 
294
    Query* wq = weight->getQuery();
 
295
        if ( query != wq ) //query was re-written
 
296
                _CLLDELETE(wq);
 
297
        _CLLDELETE(weight);
 
298
 
 
299
    SortField** hqFields = hq.getFields();
 
300
        hq.setFields(NULL); //move ownership of memory over to TopFieldDocs
 
301
    int32_t totalHits0 = totalHits[0];
 
302
        if ( bits != NULL && filter->shouldDeleteBitSet(bits) )
 
303
                _CLLDELETE(bits);
 
304
    _CLDELETE_LARRAY(totalHits);
 
305
    return _CLNEW TopFieldDocs(totalHits0, fieldDocs, hqLen, hqFields );
 
306
  }
 
307
 
 
308
  void IndexSearcher::_search(Query* query, Filter* filter, HitCollector* results){
 
309
  //Func - _search an index and fetch the results
 
310
  //       Applications should only use this if they need all of the
 
311
  //       matching documents.  The high-level search API (search(Query)) is usually more efficient, 
 
312
  //       as it skips non-high-scoring hits.
 
313
  //Pre  - query is a valid reference to a query
 
314
  //       filter may or may not be NULL
 
315
  //       results is a valid reference to a HitCollector and used to store the results
 
316
  //Post - filter if non-NULL, a bitset used to eliminate some documents
 
317
 
 
318
      CND_PRECONDITION(reader != NULL, "reader is NULL");
 
319
      CND_PRECONDITION(query != NULL, "query is NULL");
 
320
 
 
321
      BitSet* bits = NULL;
 
322
      SimpleFilteredCollector* fc = NULL; 
 
323
 
 
324
      if (filter != NULL){
 
325
          bits = filter->bits(reader);
 
326
          fc = _CLNEW SimpleFilteredCollector(bits, results);
 
327
       }
 
328
 
 
329
      Weight* weight = query->weight(this);
 
330
      Scorer* scorer = weight->scorer(reader);
 
331
      if (scorer != NULL) {
 
332
                  if (fc == NULL){
 
333
              scorer->score(results);
 
334
                  }else{
 
335
              scorer->score((HitCollector*)fc);
 
336
                  }
 
337
          _CLDELETE(scorer); 
 
338
      }
 
339
 
 
340
    _CLLDELETE(fc);
 
341
        Query* wq = weight->getQuery();
 
342
        if (wq != query) // query was rewritten
 
343
                _CLLDELETE(wq);
 
344
        _CLLDELETE(weight);
 
345
        if ( bits != NULL && filter->shouldDeleteBitSet(bits) )
 
346
                _CLLDELETE(bits);
 
347
  }
 
348
 
 
349
  Query* IndexSearcher::rewrite(Query* original) {
 
350
        Query* query = original;
 
351
                Query* last = original;
 
352
        for (Query* rewrittenQuery = query->rewrite(reader); 
 
353
                                rewrittenQuery != query;
 
354
                                rewrittenQuery = query->rewrite(reader)) {
 
355
                        query = rewrittenQuery;
 
356
                        if ( query != last && last != original ){
 
357
                                _CLLDELETE(last);
 
358
                        }
 
359
                        last = query;
 
360
        }
 
361
        return query;
 
362
    }
 
363
 
 
364
    void IndexSearcher::explain(Query* query, int32_t doc, Explanation* ret){
 
365
        Weight* weight = query->weight(this);
 
366
        ret->addDetail(weight->explain(reader, doc)); // TODO: A hack until this function will return Explanation* as well
 
367
 
 
368
        Query* wq = weight->getQuery();
 
369
            if ( query != wq ) //query was re-written
 
370
                  _CLLDELETE(wq);
 
371
        _CLDELETE(weight);
 
372
    }
 
373
 
 
374
        CL_NS(index)::IndexReader* IndexSearcher::getReader(){
 
375
                return reader;
 
376
        }
 
377
 
 
378
        const char* IndexSearcher::getClassName(){
 
379
                return "IndexSearcher";
 
380
        }
 
381
        const char* IndexSearcher::getObjectName() const{
 
382
                return IndexSearcher::getClassName();
 
383
        }
 
384
        
 
385
CL_NS_END