View Javadoc
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 }