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 | #ifndef _lucene_search_FieldSortedHitQueue_ |
8 | #define _lucene_search_FieldSortedHitQueue_ |
9 | |
10 | #if defined(_LUCENE_PRAGMA_ONCE) |
11 | # pragma once |
12 | #endif |
13 | |
14 | #include "FieldCache.h" |
15 | #include "Sort.h" |
16 | #include "FieldDocSortedHitQueue.h" |
17 | #include "SearchHeader.h" |
18 | #include "FieldCacheImpl.h" |
19 | #include "CLucene/util/PriorityQueue.h" |
20 | |
21 | CL_NS_DEF(search) |
22 | |
23 | |
24 | /** |
25 | * Expert: A hit queue for sorting by hits by terms in more than one field. |
26 | * Uses <code>FieldCache.DEFAULT</code> for maintaining internal term lookup tables. |
27 | * |
28 | * @see Searchable#search(Query,Filter,int32_t,Sort) |
29 | * @see FieldCache |
30 | */ |
31 | class FieldSortedHitQueue: public CL_NS(util)::PriorityQueue<FieldDoc*, |
32 | CL_NS(util)::Deletor::Object<FieldDoc> > { |
33 | |
34 | ///the type that is stored in the field cache. can't use a typedef because |
35 | ///the decorated name would become too long |
36 | class hitqueueCacheReaderType: public CL_NS(util)::CLHashMap<FieldCacheImpl::FileEntry*, |
37 | ScoreDocComparator*, |
38 | FieldCacheImpl::FileEntry::Compare, |
39 | FieldCacheImpl::FileEntry::Equals, |
40 | CL_NS(util)::Deletor::Object<FieldCacheImpl::FileEntry>, |
41 | CL_NS(util)::Deletor::Object<ScoreDocComparator> >{ |
42 | |
43 | public: |
44 | hitqueueCacheReaderType(bool deleteValue){ |
45 | setDeleteKey(true); |
46 | setDeleteValue(deleteValue); |
47 | } |
48 | ~hitqueueCacheReaderType(){ |
49 | clear(); |
50 | } |
51 | |
52 | }; |
53 | |
54 | public: //todo: remove this and below after close callback is implemented |
55 | //note: typename gets too long if using cacheReaderType as a typename |
56 | typedef CL_NS(util)::CLHashMap<CL_NS(index)::IndexReader*, |
57 | hitqueueCacheReaderType*, |
58 | CL_NS(util)::Compare::Void<CL_NS(index)::IndexReader>, |
59 | CL_NS(util)::Equals::Void<CL_NS(index)::IndexReader>, |
60 | CL_NS(util)::Deletor::Object<CL_NS(index)::IndexReader>, |
61 | CL_NS(util)::Deletor::Object<hitqueueCacheReaderType> > hitqueueCacheType; |
62 | |
63 | /** Internal cache of comparators. Similar to FieldCache, only |
64 | * caches comparators instead of term values. |
65 | */ |
66 | static hitqueueCacheType Comparators; |
67 | private: |
68 | |
69 | /** Returns a comparator if it is in the cache.*/ |
70 | static ScoreDocComparator* lookup (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory); |
71 | |
72 | /** Stores a comparator into the cache. |
73 | returns the valid ScoreDocComparator. |
74 | */ |
75 | static void store (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory, ScoreDocComparator* value); |
76 | |
77 | |
78 | //todo: Locale locale, not implemented yet |
79 | static ScoreDocComparator* getCachedComparator (CL_NS(index)::IndexReader* reader, |
80 | const TCHAR* fieldname, int32_t type, SortComparatorSource* factory); |
81 | |
82 | |
83 | /** |
84 | * Returns a comparator for sorting hits according to a field containing integers. |
85 | * @param reader Index to use. |
86 | * @param fieldname Field containg integer values. |
87 | * @return Comparator for sorting hits. |
88 | * @throws IOException If an error occurs reading the index. |
89 | */ |
90 | static ScoreDocComparator* comparatorInt (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); |
91 | |
92 | /** |
93 | * Returns a comparator for sorting hits according to a field containing floats. |
94 | * @param reader Index to use. |
95 | * @param fieldname Field containg float values. |
96 | * @return Comparator for sorting hits. |
97 | * @throws IOException If an error occurs reading the index. |
98 | */ |
99 | static ScoreDocComparator* comparatorFloat (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); |
100 | |
101 | /** |
102 | * Returns a comparator for sorting hits according to a field containing strings. |
103 | * @param reader Index to use. |
104 | * @param fieldname Field containg string values. |
105 | * @return Comparator for sorting hits. |
106 | * @throws IOException If an error occurs reading the index. |
107 | */ |
108 | static ScoreDocComparator* comparatorString (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); |
109 | |
110 | |
111 | //todo: |
112 | /** |
113 | * Returns a comparator for sorting hits according to a field containing strings. |
114 | * @param reader Index to use. |
115 | * @param fieldname Field containg string values. |
116 | * @return Comparator for sorting hits. |
117 | * @throws IOException If an error occurs reading the index. |
118 | |
119 | static ScoreDocComparator* comparatorStringLocale (IndexReader* reader, TCHAR* fieldname, Locale locale){ |
120 | Collator collator = Collator.getInstance (locale); |
121 | TCHAR* field = fieldname.intern(); |
122 | TCHAR** index = FieldCache.DEFAULT.getStrings (reader, field); |
123 | return _CLNEW ScoreDocComparator() { |
124 | |
125 | public int32_t compare (ScoreDoc i, ScoreDoc j) { |
126 | return collator.compare (index[i.doc], index[j.doc]); |
127 | } |
128 | |
129 | public Comparable sortValue (ScoreDoc i) { |
130 | return index[i.doc]; |
131 | } |
132 | |
133 | public int32_t sortType() { |
134 | return SortField.STRING; |
135 | } |
136 | }; |
137 | }*/ |
138 | |
139 | /** |
140 | * Returns a comparator for sorting hits according to values in the given field. |
141 | * The terms in the field are looked at to determine whether they contain integers, |
142 | * floats or strings. Once the type is determined, one of the other static methods |
143 | * in this class is called to get the comparator. |
144 | * @param reader Index to use. |
145 | * @param fieldname Field containg values. |
146 | * @return Comparator for sorting hits. |
147 | * @throws IOException If an error occurs reading the index. |
148 | */ |
149 | static ScoreDocComparator* comparatorAuto (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); |
150 | |
151 | |
152 | protected: |
153 | /** Stores a comparator corresponding to each field being sorted by */ |
154 | ScoreDocComparator** comparators; |
155 | int32_t comparatorsLen; |
156 | |
157 | /** Stores the sort criteria being used. */ |
158 | SortField** fields; |
159 | int32_t fieldsLen; |
160 | |
161 | /** Stores the maximum score value encountered, for normalizing. |
162 | * we only care about scores greater than 1.0 - if all the scores |
163 | * are less than 1.0, we don't have to normalize. */ |
164 | qreal maxscore; |
165 | |
166 | /** |
167 | * Returns whether <code>a</code> is less relevant than <code>b</code>. |
168 | * @param a ScoreDoc |
169 | * @param b ScoreDoc |
170 | * @return <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>. |
171 | */ |
172 | bool lessThan (FieldDoc* docA, FieldDoc* docB); |
173 | public: |
174 | |
175 | /** |
176 | * Creates a hit queue sorted by the given list of fields. |
177 | * @param reader Index to use. |
178 | * @param fields Field names, in priority order (highest priority first). Cannot be <code>null</code> or empty. |
179 | * @param size The number of hits to retain. Must be greater than zero. |
180 | * @throws IOException |
181 | */ |
182 | FieldSortedHitQueue (CL_NS(index)::IndexReader* reader, SortField** fields, int32_t size); |
183 | |
184 | ~FieldSortedHitQueue(); |
185 | |
186 | /** |
187 | * Callback for when IndexReader closes. This causes |
188 | * any Comparators to be removed for the specified reader. |
189 | */ |
190 | static void closeCallback(CL_NS(index)::IndexReader* reader, void* param); |
191 | |
192 | /** |
193 | * Given a FieldDoc object, stores the values used |
194 | * to sort the given document. These values are not the raw |
195 | * values out of the index, but the internal representation |
196 | * of them. This is so the given search hit can be collated |
197 | * by a MultiSearcher with other search hits. |
198 | * @param doc The FieldDoc to store sort values into. |
199 | * @return The same FieldDoc passed in. |
200 | * @see Searchable#search(Query,Filter,int32_t,Sort) |
201 | */ |
202 | FieldDoc* fillFields (FieldDoc* doc) const; |
203 | |
204 | void setFields (SortField** fields){ |
205 | this->fields = fields; |
206 | } |
207 | |
208 | /** Returns the SortFields being used by this hit queue. */ |
209 | SortField** getFields() { |
210 | return fields; |
211 | } |
212 | }; |
213 | |
214 | |
215 | CL_NS_END |
216 | #endif |
217 | |