/*------------------------------------------------------------------------------ * 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_Sort_ #define _lucene_search_Sort_ #if defined(_LUCENE_PRAGMA_ONCE) # pragma once #endif #include "CLucene/index/IndexReader.h" #include "ScoreDoc.h" CL_NS_DEF(search) class SortField; //predefine class Sort; /** * Expert: Compares two ScoreDoc objects for sorting. * */ class ScoreDocComparator:LUCENE_BASE { protected: ScoreDocComparator(){} public: virtual ~ScoreDocComparator(); // CL_NS(util)::Comparable** cachedValues; // ScoreDocComparator(CL_NS(util)::Comparable** cachedValues); /** * Compares two ScoreDoc objects and returns a result indicating their * sort order. * @param i First ScoreDoc * @param j Second ScoreDoc * @return -1 if i should come before j
1 if i should come after j
0 if they are equal * @see java.util.Comparator */ virtual int32_t compare (ScoreDoc* i, ScoreDoc* j) = 0; /** * Returns the value used to sort the given document. The * object returned must implement the java.io.Serializable * interface. This is used by multisearchers to determine how to collate results from their searchers. * @see FieldDoc * @param i Document * @return Serializable object */ virtual CL_NS(util)::Comparable* sortValue (ScoreDoc* i) = 0; /** * Returns the type of sort. Should return SortField.SCORE, SortField.DOC, SortField.STRING, SortField.INTEGER, * SortField::FLOAT or SortField.CUSTOM. It is not valid to return SortField.AUTO. * This is used by multisearchers to determine how to collate results from their searchers. * @return One of the constants in SortField. * @see SortField */ virtual int32_t sortType() = 0; /** Special comparator for sorting hits according to computed relevance (document score). */ static ScoreDocComparator* RELEVANCE; /** Special comparator for sorting hits according to index order (document number). */ static ScoreDocComparator* INDEXORDER; }; /** * Expert: returns a comparator for sorting ScoreDocs. * */ class SortComparatorSource:LUCENE_BASE { public: virtual ~SortComparatorSource(){ } /** * return a reference to a string describing the name of the comparator * this is used in the explanation */ virtual TCHAR* getName() = 0; virtual size_t hashCode() = 0; /** * Creates a comparator for the field in the given index. * @param reader Index to create comparator for. * @param fieldname Field to create comparator for. * @return Comparator of ScoreDoc objects. * @throws IOException If an error occurs reading the index. */ virtual ScoreDocComparator* newComparator (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname) = 0; }; /** * Abstract base class for sorting hits returned by a Query. * *

This class should only be used if the other SortField * types (SCORE, DOC, STRING, INT, FLOAT) do not provide an * adequate sorting. It maintains an internal cache of values which * could be quite large. The cache is an array of Comparable, * one for each document in the index. There is a distinct * Comparable for each unique term in the field - if * some documents have the same term in the field, the cache * array will have entries which reference the same Comparable. * */ class SortComparator: public SortComparatorSource { ScoreDocComparator* _this; public: ScoreDocComparator* newComparator (CL_NS(index)::IndexReader* reader, TCHAR* fieldname); SortComparator(ScoreDocComparator* _this); virtual ~SortComparator(); /** * Returns an object which, when sorted according to natural order, * will order the Term values in the correct order. *

For example, if the Terms contained integer values, this method * would return new Integer(termtext). Note that this * might not always be the most efficient implementation - for this * particular example, a better implementation might be to make a * ScoreDocLookupComparator that uses an internal lookup table of int. * @param termtext The textual value of the term. * @return An object representing termtext that sorts * according to the natural order of termtext. * @see Comparable * @see ScoreDocComparator */ virtual CL_NS(util)::Comparable* getComparable (const TCHAR* termtext) = 0; }; /** * Stores information about how to sort documents by terms in an individual * field. Fields must be indexed in order to sort by them. * */ class SortField:LUCENE_BASE { private: const TCHAR* field; int32_t type; // defaults to determining type dynamically //Locale* locale; // defaults to "natural order" (no Locale) bool reverse; // defaults to natural order SortComparatorSource* factory; protected: SortField (const SortField& clone); public: virtual ~SortField(); /** Sort by document score (relevancy). Sort values are Float and higher * values are at the front. * PORTING: this is the same as SCORE in java, it had to be renamed because * SCORE is a system macro on some platforms (AIX). */ LUCENE_STATIC_CONSTANT(int32_t, DOCSCORE=0); /** Sort by document number (index order). Sort values are Integer and lower * values are at the front. */ LUCENE_STATIC_CONSTANT(int32_t, DOC=1); /** Guess type of sort based on field contents. A regular expression is used * to look at the first term indexed for the field and determine if it * represents an integer number, a floating point number, or just arbitrary * string characters. */ LUCENE_STATIC_CONSTANT(int32_t, AUTO=2); /** Sort using term values as Strings. Sort values are String and lower * values are at the front. */ LUCENE_STATIC_CONSTANT(int32_t, STRING=3); /** Sort using term values as encoded Integers. Sort values are Integer and * lower values are at the front. */ LUCENE_STATIC_CONSTANT(int32_t, INT=4); /** Sort using term values as encoded Floats. Sort values are Float and * lower values are at the front. */ LUCENE_STATIC_CONSTANT(int32_t, FLOAT=5); /** Sort using a custom Comparator. Sort values are any Comparable and * sorting is done according to natural order. */ LUCENE_STATIC_CONSTANT(int32_t, CUSTOM=9); // IMPLEMENTATION NOTE: the FieldCache.STRING_INDEX is in the same "namespace" // as the above static int values. Any new values must not have the same value // as FieldCache.STRING_INDEX. /** Represents sorting by document score (relevancy). */ static SortField* FIELD_SCORE; /** Represents sorting by document number (index order). */ static SortField* FIELD_DOC; SortField (const TCHAR* field); //SortField (const TCHAR* field, bool reverse); //todo: we cannot make reverse use default field of =false. //because bool and int are the same type in c, overloading is not possible SortField (const TCHAR* field, int32_t type, bool reverse); /* SortField (TCHAR* field, Locale* locale) { SortField (TCHAR* field, Locale* locale, bool reverse);*/ SortField (const TCHAR* field, SortComparatorSource* comparator, bool reverse=false); /** Returns the name of the field. Could return null * if the sort is by SCORE or DOC. * @return Name of field, possibly null. */ const TCHAR* getField() const { return field; } SortField* clone() const; /** Returns the type of contents in the field. * @return One of the constants SCORE, DOC, AUTO, STRING, INT or FLOAT. */ int32_t getType() const { return type; } /** Returns the Locale by which term values are interpreted. * May return null if no Locale was specified. * @return Locale, or null. */ /*Locale getLocale() { return locale; }*/ /** Returns whether the sort should be reversed. * @return True if natural order should be reversed. */ bool getReverse() const { return reverse; } SortComparatorSource* getFactory() { return factory; } const TCHAR* toString() const; }; /** * Encapsulates sort criteria for returned hits. * *

The fields used to determine sort order must be carefully chosen. * Documents must contain a single term in such a field, * and the value of the term should indicate the document's relative position in * a given sort order. The field must be indexed, but should not be tokenized, * and does not need to be stored (unless you happen to want it back with the * rest of your document data). In other words: * *

document.add (new Field ("byNumber", Integer.toString(x), false, true, false)); *
* *

Valid Types of Values

* *

There are three possible kinds of term values which may be put into * sorting fields: Integers, Floats, or Strings. Unless * {@link SortField SortField} objects are specified, the type of value * in the field is determined by parsing the first term in the field. * *

Integer term values should contain only digits and an optional * preceeding negative sign. Values must be base 10 and in the range * Integer.MIN_VALUE and Integer.MAX_VALUE inclusive. * Documents which should appear first in the sort * should have low value integers, later documents high values * (i.e. the documents should be numbered 1..n where * 1 is the first and n the last). * *

Float term values should conform to values accepted by * {@link Float Float.valueOf(String)} (except that NaN * and Infinity are not supported). * Documents which should appear first in the sort * should have low values, later documents high values. * *

String term values can contain any valid String, but should * not be tokenized. The values are sorted according to their * {@link Comparable natural order}. Note that using this type * of term value has higher memory requirements than the other * two types. * *

Object Reuse

* *

One of these objects can be * used multiple times and the sort order changed between usages. * *

This class is thread safe. * *

Memory Usage

* *

Sorting uses of caches of term values maintained by the * internal HitQueue(s). The cache is static and contains an integer * or float array of length IndexReader.maxDoc() for each field * name for which a sort is performed. In other words, the size of the * cache in bytes is: * *

4 * IndexReader.maxDoc() * (# of different fields actually used to sort) * *

For String fields, the cache is larger: in addition to the * above array, the value of every term in the field is kept in memory. * If there are many unique terms in the field, this could * be quite large. * *

Note that the size of the cache is not affected by how many * fields are in the index and might be used to sort - only by * the ones actually used to sort a result set. * *

The cache is cleared each time a new IndexReader is * passed in, or if the value returned by maxDoc() * changes for the current IndexReader. This class is not set up to * be able to efficiently sort hits from more than one index * simultaneously. * */ class Sort:LUCENE_BASE { // internal representation of the sort criteria SortField** fields; void clear(); public: ~Sort(); /** Represents sorting by computed relevance. Using this sort criteria * returns the same results as calling {@link Searcher#search(Query) Searcher#search()} * without a sort criteria, only with slightly more overhead. */ static Sort* RELEVANCE; /** Represents sorting by index order. */ static Sort* INDEXORDER; Sort(); Sort (const TCHAR* field, bool reverse=false); Sort (const TCHAR** fields); Sort (SortField* field); Sort (SortField** fields); void setSort (const TCHAR* field, bool reverse=false); void setSort (const TCHAR** fieldnames); void setSort (SortField* field); void setSort (SortField** fields); const TCHAR* toString() const; /** * Representation of the sort criteria. * @return a pointer to the of SortField array used in this sort criteria */ SortField** getSort() const{ return fields; } }; CL_NS_END #endif