1 /*
2 * Copyright 2012-2025 CodeLibs Project and the Others.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 * either express or implied. See the License for the specific language
14 * governing permissions and limitations under the License.
15 */
16 package org.codelibs.fess.rank.fusion;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.apache.lucene.search.TotalHits.Relation;
23 import org.codelibs.fess.util.FacetResponse;
24
25 /**
26 * Represents the result of a search operation in the rank fusion system.
27 *
28 * This class encapsulates all the information returned from a search query,
29 * including the list of matching documents, total record count, query execution
30 * time, facet information, and metadata about the search results.
31 */
32 public class SearchResult {
33
34 /** The list of documents returned by the search query. */
35 protected final List<Map<String, Object>> documentList;
36
37 /** The total number of records that match the search criteria. */
38 protected final long allRecordCount;
39
40 /** The relation type indicating how the record count should be interpreted (e.g., "eq", "gte"). */
41 protected final String allRecordCountRelation;
42
43 /** The time taken to execute the search query in milliseconds. */
44 protected final long queryTime;
45
46 /** Flag indicating whether the search results are partial due to timeout or other constraints. */
47 protected final boolean partialResults;
48
49 /** The facet response containing aggregated facet information for the search results. */
50 protected final FacetResponse facetResponse;
51
52 /**
53 * Constructs a new SearchResult with the specified parameters.
54 *
55 * @param documentList The list of documents returned by the search
56 * @param allRecordCount The total number of matching records
57 * @param allRecordCountRelation The relation type for the record count
58 * @param queryTime The time taken to execute the query in milliseconds
59 * @param partialResults Whether the results are partial
60 * @param facetResponse The facet response containing aggregated data
61 */
62 SearchResult(final List<Map<String, Object>> documentList, final long allRecordCount, final String allRecordCountRelation,
63 final long queryTime, final boolean partialResults, final FacetResponse facetResponse) {
64 this.documentList = documentList;
65 this.allRecordCount = allRecordCount;
66 this.allRecordCountRelation = allRecordCountRelation;
67 this.queryTime = queryTime;
68 this.partialResults = partialResults;
69 this.facetResponse = facetResponse;
70 }
71
72 /**
73 * Gets the list of documents returned by the search query.
74 *
75 * @return The list of search result documents
76 */
77 public List<Map<String, Object>> getDocumentList() {
78 return documentList;
79 }
80
81 /**
82 * Gets the total number of records that match the search criteria.
83 *
84 * @return The total record count
85 */
86 public long getAllRecordCount() {
87 return allRecordCount;
88 }
89
90 /**
91 * Gets the relation type indicating how the record count should be interpreted.
92 *
93 * @return The record count relation (e.g., "eq" for exact, "gte" for greater than or equal)
94 */
95 public String getAllRecordCountRelation() {
96 return allRecordCountRelation;
97 }
98
99 /**
100 * Gets the time taken to execute the search query.
101 *
102 * @return The query execution time in milliseconds
103 */
104 public long getQueryTime() {
105 return queryTime;
106 }
107
108 /**
109 * Checks whether the search results are partial due to timeout or other constraints.
110 *
111 * @return true if the results are partial, false if complete
112 */
113 public boolean isPartialResults() {
114 return partialResults;
115 }
116
117 /**
118 * Gets the facet response containing aggregated facet information.
119 *
120 * @return The facet response, or null if no facets were requested
121 */
122 public FacetResponse getFacetResponse() {
123 return facetResponse;
124 }
125
126 /**
127 * Creates a new SearchResultBuilder for constructing SearchResult instances.
128 *
129 * @return A new SearchResultBuilder instance
130 */
131 public static SearchResultBuilder create() {
132 return new SearchResultBuilder();
133 }
134
135 @Override
136 public String toString() {
137 return "SearchResult [documentList=" + documentList + ", allRecordCount=" + allRecordCount + ", allRecordCountRelation="
138 + allRecordCountRelation + ", queryTime=" + queryTime + ", partialResults=" + partialResults + ", facetResponse="
139 + facetResponse + "]";
140 }
141
142 /**
143 * Builder class for constructing SearchResult instances using the builder pattern.
144 *
145 * This builder provides a fluent interface for setting the various properties
146 * of a SearchResult before creating the final immutable instance.
147 */
148 static class SearchResultBuilder {
149
150 /** The total number of records that match the search criteria. */
151 private long allRecordCount;
152
153 /** The relation type for the record count, defaults to greater than or equal to. */
154 private String allRecordCountRelation = Relation.GREATER_THAN_OR_EQUAL_TO.toString();
155
156 /** The time taken to execute the search query in milliseconds. */
157 private long queryTime;
158
159 /** Flag indicating whether the search results are partial. */
160 private boolean partialResults;
161
162 /** The facet response containing aggregated facet information. */
163 private FacetResponse facetResponse;
164
165 /** The list of documents to be included in the search result. */
166 private final List<Map<String, Object>> documentList = new ArrayList<>();
167
168 /**
169 * Sets the total number of records that match the search criteria.
170 *
171 * @param allRecordCount The total record count
172 * @return This builder instance for method chaining
173 */
174 public SearchResultBuilder allRecordCount(final long allRecordCount) {
175 this.allRecordCount = allRecordCount;
176 return this;
177 }
178
179 /**
180 * Sets the relation type for the record count.
181 *
182 * @param allRecordCountRelation The record count relation (e.g., "eq", "gte")
183 * @return This builder instance for method chaining
184 */
185 public SearchResultBuilder allRecordCountRelation(final String allRecordCountRelation) {
186 this.allRecordCountRelation = allRecordCountRelation;
187 return this;
188 }
189
190 /**
191 * Sets the time taken to execute the search query.
192 *
193 * @param queryTime The query execution time in milliseconds
194 * @return This builder instance for method chaining
195 */
196 public SearchResultBuilder queryTime(final long queryTime) {
197 this.queryTime = queryTime;
198 return this;
199 }
200
201 /**
202 * Sets whether the search results are partial.
203 *
204 * @param partialResults true if the results are partial, false if complete
205 * @return This builder instance for method chaining
206 */
207 public SearchResultBuilder partialResults(final boolean partialResults) {
208 this.partialResults = partialResults;
209 return this;
210 }
211
212 /**
213 * Adds a document to the search result.
214 *
215 * @param doc The document to add to the result list
216 * @return This builder instance for method chaining
217 */
218 public SearchResultBuilder addDocument(final Map<String, Object> doc) {
219 documentList.add(doc);
220 return this;
221 }
222
223 /**
224 * Sets the facet response containing aggregated facet information.
225 *
226 * @param facetResponse The facet response
227 * @return This builder instance for method chaining
228 */
229 public SearchResultBuilder facetResponse(final FacetResponse facetResponse) {
230 this.facetResponse = facetResponse;
231 return this;
232 }
233
234 /**
235 * Builds and returns the final SearchResult instance.
236 *
237 * @return A new SearchResult instance with the configured properties
238 */
239 public SearchResult build() {
240 return new SearchResult(documentList, //
241 allRecordCount, //
242 allRecordCountRelation, //
243 queryTime, //
244 partialResults, //
245 facetResponse);
246 }
247 }
248 }