|
17 | 17 | from django.utils.functional import cached_property
|
18 | 18 | from pymongo import ASCENDING, DESCENDING
|
19 | 19 |
|
20 |
| -from .expressions.builtins import SearchExpression |
| 20 | +from .expressions.builtins import SearchExpression, SearchVector |
21 | 21 | from .query import MongoQuery, wrap_database_errors
|
22 | 22 |
|
23 | 23 |
|
@@ -117,29 +117,24 @@ def _prepare_search_expressions_for_pipeline(
|
117 | 117 | if sub_expr not in replacements:
|
118 | 118 | alias = f"__search_expr.search{next(search_idx)}"
|
119 | 119 | replacements[sub_expr] = self._get_replace_expr(sub_expr, searches, alias)
|
120 |
| - return list(searches.values()) |
121 | 120 |
|
122 | 121 | def _prepare_search_query_for_aggregation_pipeline(self, order_by):
|
123 | 122 | replacements = {}
|
124 |
| - searches = [] |
125 | 123 | annotation_group_idx = itertools.count(start=1)
|
126 | 124 | for target, expr in self.query.annotation_select.items():
|
127 |
| - expr_searches = self._prepare_search_expressions_for_pipeline( |
| 125 | + self._prepare_search_expressions_for_pipeline( |
128 | 126 | expr, target, annotation_group_idx, replacements
|
129 | 127 | )
|
130 |
| - searches += expr_searches |
131 | 128 |
|
132 | 129 | for expr, _ in order_by:
|
133 |
| - expr_searches = self._prepare_search_expressions_for_pipeline( |
| 130 | + self._prepare_search_expressions_for_pipeline( |
134 | 131 | expr, None, annotation_group_idx, replacements
|
135 | 132 | )
|
136 |
| - searches += expr_searches |
137 | 133 |
|
138 |
| - having_group = self._prepare_search_expressions_for_pipeline( |
| 134 | + self._prepare_search_expressions_for_pipeline( |
139 | 135 | self.having, None, annotation_group_idx, replacements
|
140 | 136 | )
|
141 |
| - searches += having_group |
142 |
| - return searches, replacements |
| 137 | + return replacements |
143 | 138 |
|
144 | 139 | def _prepare_annotations_for_aggregation_pipeline(self, order_by):
|
145 | 140 | """Prepare annotations for the aggregation pipeline."""
|
@@ -248,22 +243,36 @@ def _build_aggregation_pipeline(self, ids, group):
|
248 | 243 | pipeline.append({"$unset": "_id"})
|
249 | 244 | return pipeline
|
250 | 245 |
|
251 |
| - def _compound_searches_queries(self, searches, search_replacements): |
252 |
| - if not searches: |
| 246 | + def _compound_searches_queries(self, search_replacements): |
| 247 | + if not search_replacements: |
253 | 248 | return []
|
254 |
| - if len(searches) > 1: |
| 249 | + if len(search_replacements) > 1: |
255 | 250 | raise ValueError("Cannot perform more than one search operation.")
|
256 |
| - score_function = "searchScore" if "$search" in searches[0] else "vectorSearchScore" |
257 |
| - return [searches[0], {"$addFields": {"__search_expr.search1": {"$meta": score_function}}}] |
| 251 | + pipeline = [] |
| 252 | + for search, result_col in search_replacements.items(): |
| 253 | + score_function = ( |
| 254 | + "vectorSearchScore" if isinstance(search, SearchVector) else "searchScore" |
| 255 | + ) |
| 256 | + pipeline.extend( |
| 257 | + [ |
| 258 | + search.as_mql(self, self.connection), |
| 259 | + { |
| 260 | + "$addFields": { |
| 261 | + result_col.as_mql(self, self.connection).removeprefix("$"): { |
| 262 | + "$meta": score_function |
| 263 | + } |
| 264 | + } |
| 265 | + }, |
| 266 | + ] |
| 267 | + ) |
| 268 | + return pipeline |
258 | 269 |
|
259 | 270 | def pre_sql_setup(self, with_col_aliases=False):
|
260 | 271 | extra_select, order_by, group_by = super().pre_sql_setup(with_col_aliases=with_col_aliases)
|
261 |
| - searches, search_replacements = self._prepare_search_query_for_aggregation_pipeline( |
262 |
| - order_by |
263 |
| - ) |
| 272 | + search_replacements = self._prepare_search_query_for_aggregation_pipeline(order_by) |
264 | 273 | group, group_replacements = self._prepare_annotations_for_aggregation_pipeline(order_by)
|
265 | 274 | all_replacements = {**search_replacements, **group_replacements}
|
266 |
| - self.search_pipeline = self._compound_searches_queries(searches, search_replacements) |
| 275 | + self.search_pipeline = self._compound_searches_queries(search_replacements) |
267 | 276 | # query.group_by is either:
|
268 | 277 | # - None: no GROUP BY
|
269 | 278 | # - True: group by select fields
|
|
0 commit comments