/*------------------------------------------------------------------------------
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
*
* Distributable under the terms of either the Apache License (Version 2.0) or
* the GNU Lesser General Public License, as specified in the COPYING file.
------------------------------------------------------------------------------*/
#ifndef _lucene_search_FieldSortedHitQueue_
#define _lucene_search_FieldSortedHitQueue_
#if defined(_LUCENE_PRAGMA_ONCE)
# pragma once
#endif
#include "ScoreDoc.h"
#include "FieldCache.h"
#include "Sort.h"
#include "FieldDoc.h"
#include "SearchHeader.h"
#include "FieldCacheImpl.h"
#include "CLucene/util/PriorityQueue.h"
CL_NS_DEF(search)
/**
* Expert: A hit queue for sorting by hits by terms in more than one field.
* Uses FieldCache.DEFAULT
for maintaining internal term lookup tables.
*
* @see Searchable#search(Query,Filter,int32_t,Sort)
* @see FieldCache
*/
class FieldSortedHitQueue: public CL_NS(util)::PriorityQueue > {
///the type that is stored in the field cache. can't use a typedef because
///the decorated name would become too long
class hitqueueCacheReaderType: public CL_NS(util)::CLHashMap,
CL_NS(util)::Deletor::Object >{
public:
hitqueueCacheReaderType(bool deleteValue){
setDeleteKey(true);
setDeleteValue(deleteValue);
}
~hitqueueCacheReaderType(){
clear();
}
};
public:
/**
* Creates a hit queue sorted by the given list of fields.
* @param reader Index to use.
* @param fields Field names, in priority order (highest priority first). Cannot be null
or empty.
* @param size The number of hits to retain. Must be greater than zero.
* @throws IOException
*/
FieldSortedHitQueue (CL_NS(index)::IndexReader* reader, SortField** fields, int32_t size);
~FieldSortedHitQueue();
protected:
/** Stores a comparator corresponding to each field being sorted by */
ScoreDocComparator** comparators;
int32_t comparatorsLen;
//note: typename gets too long if using cacheReaderType as a typename
typedef CL_NS(util)::CLHashMap,
CL_NS(util)::Deletor::Object,
CL_NS(util)::Deletor::Object > hitqueueCacheType;
/** Stores the sort criteria being used. */
SortField** fields;
int32_t fieldsLen;
/** Stores the maximum score value encountered, for normalizing.
* we only care about scores greater than 1.0 - if all the scores
* are less than 1.0, we don't have to normalize. */
float_t maxscore;
/**
* Returns whether a
is less relevant than b
.
* @param a ScoreDoc
* @param b ScoreDoc
* @return true
if document a
should be sorted after document b
.
*/
bool lessThan (FieldDoc* docA, FieldDoc* docB) {
// keep track of maximum score
if (docA->score > maxscore) maxscore = docA->score;
if (docB->score > maxscore) maxscore = docB->score;
// run comparators
int32_t c = 0;
int32_t i=0;
while ( comparators[i] != NULL && c==0 ) {
c = (fields[i]->getReverse()) ? comparators[i]->compare (docB, docA) :
comparators[i]->compare (docA, docB);
i++;
}
// avoid random sort order that could lead to duplicates (bug #31241):
if (c == 0)
return docA->doc > docB->doc;
return c > 0;
}
public:
/**
* Given a FieldDoc object, stores the values used
* to sort the given document. These values are not the raw
* values out of the index, but the internal representation
* of them. This is so the given search hit can be collated
* by a MultiSearcher with other search hits.
* @param doc The FieldDoc to store sort values into.
* @return The same FieldDoc passed in.
* @see Searchable#search(Query,Filter,int32_t,Sort)
*/
FieldDoc* fillFields (FieldDoc* doc) const;
/** Returns the SortFields being used by this hit queue. */
SortField** getFields() {
return fields;
}
/**
* Callback for when IndexReader closes. This causes
* any Comparators to be removed for the specified reader.
*/
static void closeCallback(CL_NS(index)::IndexReader* reader, void* param);
/** Internal cache of comparators. Similar to FieldCache, only
* caches comparators instead of term values.
*/
static hitqueueCacheType Comparators;
/** Returns a comparator if it is in the cache.*/
static ScoreDocComparator* lookup (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory);
/** Stores a comparator into the cache. */
static void store (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory, ScoreDocComparator* value);
//todo: Locale locale, not implemented yet
static ScoreDocComparator* getCachedComparator (CL_NS(index)::IndexReader* reader,
const TCHAR* fieldname, int32_t type, SortComparatorSource* factory);
/**
* Returns a comparator for sorting hits according to a field containing integers.
* @param reader Index to use.
* @param fieldname Field containg integer values.
* @return Comparator for sorting hits.
* @throws IOException If an error occurs reading the index.
*/
static ScoreDocComparator* comparatorInt (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
/**
* Returns a comparator for sorting hits according to a field containing floats.
* @param reader Index to use.
* @param fieldname Field containg float values.
* @return Comparator for sorting hits.
* @throws IOException If an error occurs reading the index.
*/
static ScoreDocComparator* comparatorFloat (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
/**
* Returns a comparator for sorting hits according to a field containing strings.
* @param reader Index to use.
* @param fieldname Field containg string values.
* @return Comparator for sorting hits.
* @throws IOException If an error occurs reading the index.
*/
static ScoreDocComparator* comparatorString (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
//todo:
/**
* Returns a comparator for sorting hits according to a field containing strings.
* @param reader Index to use.
* @param fieldname Field containg string values.
* @return Comparator for sorting hits.
* @throws IOException If an error occurs reading the index.
static ScoreDocComparator* comparatorStringLocale (IndexReader* reader, TCHAR* fieldname, Locale locale){
Collator collator = Collator.getInstance (locale);
TCHAR* field = fieldname.intern();
TCHAR** index = FieldCache.DEFAULT.getStrings (reader, field);
return _CLNEW ScoreDocComparator() {
public int32_t compare (ScoreDoc i, ScoreDoc j) {
return collator.compare (index[i.doc], index[j.doc]);
}
public Comparable sortValue (ScoreDoc i) {
return index[i.doc];
}
public int32_t sortType() {
return SortField.STRING;
}
};
}*/
/**
* Returns a comparator for sorting hits according to values in the given field.
* The terms in the field are looked at to determine whether they contain integers,
* floats or strings. Once the type is determined, one of the other static methods
* in this class is called to get the comparator.
* @param reader Index to use.
* @param fieldname Field containg values.
* @return Comparator for sorting hits.
* @throws IOException If an error occurs reading the index.
*/
static ScoreDocComparator* comparatorAuto (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
};
CL_NS_END
#endif