|
21 | 21 | import org.redisson.api.search.aggregate.*; |
22 | 22 | import org.redisson.api.search.index.*; |
23 | 23 | import org.redisson.api.search.query.*; |
| 24 | +import org.redisson.api.search.query.hybrid.*; |
24 | 25 | import org.redisson.client.RedisClient; |
25 | 26 | import org.redisson.client.codec.Codec; |
26 | 27 | import org.redisson.client.codec.DoubleCodec; |
@@ -1090,4 +1091,207 @@ public List<String> getIndexes() { |
1090 | 1091 | public RFuture<List<String>> getIndexesAsync() { |
1091 | 1092 | return commandExecutor.readAsync((String) null, StringCodec.INSTANCE, RedisCommands.FT_LIST); |
1092 | 1093 | } |
| 1094 | + |
| 1095 | + @Override |
| 1096 | + public HybridSearchResult hybridSearch(String indexName, HybridQueryArgs args) { |
| 1097 | + return commandExecutor.get(hybridSearchAsync(indexName, args)); |
| 1098 | + } |
| 1099 | + |
| 1100 | + @Override |
| 1101 | + @SuppressWarnings("MethodLength") |
| 1102 | + public RFuture<HybridSearchResult> hybridSearchAsync(String indexName, HybridQueryArgs args) { |
| 1103 | + HybridQueryParams options = (HybridQueryParams) args; |
| 1104 | + |
| 1105 | + List<Object> cmdArgs = new ArrayList<>(); |
| 1106 | + cmdArgs.add(indexName); |
| 1107 | + |
| 1108 | + cmdArgs.add("SEARCH"); |
| 1109 | + cmdArgs.add(options.getQuery()); |
| 1110 | + |
| 1111 | + if (options.getScorer() != null) { |
| 1112 | + cmdArgs.add("SCORER"); |
| 1113 | + cmdArgs.add(options.getScorer()); |
| 1114 | + } |
| 1115 | + |
| 1116 | + if (options.getQueryScoreAlias() != null) { |
| 1117 | + cmdArgs.add("YIELD_SCORE_AS"); |
| 1118 | + cmdArgs.add(options.getQueryScoreAlias()); |
| 1119 | + } |
| 1120 | + |
| 1121 | + VectorSimilarityParams vsimParams = options.getVectorSimilarityParams(); |
| 1122 | + if (vsimParams == null) { |
| 1123 | + throw new IllegalArgumentException("vectorSimilarity is required for hybrid search"); |
| 1124 | + } |
| 1125 | + cmdArgs.add("VSIM"); |
| 1126 | + cmdArgs.add(vsimParams.getField()); |
| 1127 | + cmdArgs.add(vsimParams.getParam()); |
| 1128 | + |
| 1129 | + if (vsimParams.getMode() == VectorSimilarityParams.VectorSearchMode.KNN) { |
| 1130 | + List<Object> knnArgs = new ArrayList<>(); |
| 1131 | + knnArgs.add("K"); |
| 1132 | + knnArgs.add(vsimParams.getKnnK()); |
| 1133 | + if (vsimParams.getEfRuntime() != null) { |
| 1134 | + knnArgs.add("EF_RUNTIME"); |
| 1135 | + knnArgs.add(vsimParams.getEfRuntime()); |
| 1136 | + } |
| 1137 | + cmdArgs.add("KNN"); |
| 1138 | + cmdArgs.add(knnArgs.size()); |
| 1139 | + cmdArgs.addAll(knnArgs); |
| 1140 | + } else if (vsimParams.getMode() == VectorSimilarityParams.VectorSearchMode.RANGE) { |
| 1141 | + List<Object> rangeArgs = new ArrayList<>(); |
| 1142 | + rangeArgs.add("RADIUS"); |
| 1143 | + rangeArgs.add(vsimParams.getRangeRadius()); |
| 1144 | + if (vsimParams.getRangeEpsilon() != null) { |
| 1145 | + rangeArgs.add("EPSILON"); |
| 1146 | + rangeArgs.add(vsimParams.getRangeEpsilon()); |
| 1147 | + } |
| 1148 | + cmdArgs.add("RANGE"); |
| 1149 | + cmdArgs.add(rangeArgs.size()); |
| 1150 | + cmdArgs.addAll(rangeArgs); |
| 1151 | + } |
| 1152 | + |
| 1153 | + if (vsimParams.getScoreAlias() != null) { |
| 1154 | + cmdArgs.add("YIELD_SCORE_AS"); |
| 1155 | + cmdArgs.add(vsimParams.getScoreAlias()); |
| 1156 | + } |
| 1157 | + |
| 1158 | + if (vsimParams.getFilter() != null) { |
| 1159 | + cmdArgs.add("FILTER"); |
| 1160 | + cmdArgs.add(vsimParams.getFilter()); |
| 1161 | + } |
| 1162 | + |
| 1163 | + Combine combine = options.getCombine(); |
| 1164 | + if (combine != null) { |
| 1165 | + cmdArgs.add("COMBINE"); |
| 1166 | + if (combine instanceof CombineRrfParams) { |
| 1167 | + CombineRrfParams rrfParams = (CombineRrfParams) combine; |
| 1168 | + List<Object> combineArgs = new ArrayList<>(); |
| 1169 | + if (rrfParams.getConstant() != null) { |
| 1170 | + combineArgs.add("CONSTANT"); |
| 1171 | + combineArgs.add(rrfParams.getConstant()); |
| 1172 | + } |
| 1173 | + if (rrfParams.getWindow() != null) { |
| 1174 | + combineArgs.add("WINDOW"); |
| 1175 | + combineArgs.add(rrfParams.getWindow()); |
| 1176 | + } |
| 1177 | + cmdArgs.add("RRF"); |
| 1178 | + cmdArgs.add(combineArgs.size()); |
| 1179 | + cmdArgs.addAll(combineArgs); |
| 1180 | + |
| 1181 | + if (rrfParams.getScoreAlias() != null) { |
| 1182 | + cmdArgs.add("YIELD_SCORE_AS"); |
| 1183 | + cmdArgs.add(rrfParams.getScoreAlias()); |
| 1184 | + } |
| 1185 | + } else if (combine instanceof CombineLinearParams) { |
| 1186 | + CombineLinearParams linearParams = (CombineLinearParams) combine; |
| 1187 | + List<Object> combineArgs = new ArrayList<>(); |
| 1188 | + if (linearParams.getAlpha() != null) { |
| 1189 | + combineArgs.add("ALPHA"); |
| 1190 | + combineArgs.add(linearParams.getAlpha()); |
| 1191 | + } |
| 1192 | + if (linearParams.getBeta() != null) { |
| 1193 | + combineArgs.add("BETA"); |
| 1194 | + combineArgs.add(linearParams.getBeta()); |
| 1195 | + } |
| 1196 | + if (linearParams.getWindow() != null) { |
| 1197 | + combineArgs.add("WINDOW"); |
| 1198 | + combineArgs.add(linearParams.getWindow()); |
| 1199 | + } |
| 1200 | + cmdArgs.add("LINEAR"); |
| 1201 | + cmdArgs.add(combineArgs.size()); |
| 1202 | + cmdArgs.addAll(combineArgs); |
| 1203 | + |
| 1204 | + // YIELD_SCORE_AS for combined score |
| 1205 | + if (linearParams.getScoreAlias() != null) { |
| 1206 | + cmdArgs.add("YIELD_SCORE_AS"); |
| 1207 | + cmdArgs.add(linearParams.getScoreAlias()); |
| 1208 | + } |
| 1209 | + } |
| 1210 | + } |
| 1211 | + |
| 1212 | + if (options.getLimitOffset() != null && options.getLimitCount() != null) { |
| 1213 | + cmdArgs.add("LIMIT"); |
| 1214 | + cmdArgs.add(options.getLimitOffset()); |
| 1215 | + cmdArgs.add(options.getLimitCount()); |
| 1216 | + } |
| 1217 | + |
| 1218 | + if (options.getSortFieldName() != null) { |
| 1219 | + cmdArgs.add("SORTBY"); |
| 1220 | + if (options.getSortOrder() != null) { |
| 1221 | + cmdArgs.add(2); |
| 1222 | + } else { |
| 1223 | + cmdArgs.add(1); |
| 1224 | + } |
| 1225 | + cmdArgs.add(options.getSortFieldName()); |
| 1226 | + if (options.getSortOrder() != null) { |
| 1227 | + cmdArgs.add(options.getSortOrder().name()); |
| 1228 | + } |
| 1229 | + } |
| 1230 | + |
| 1231 | + if (options.isNoSort()) { |
| 1232 | + cmdArgs.add("NOSORT"); |
| 1233 | + } |
| 1234 | + |
| 1235 | + if (options.getLoadFields() != null && !options.getLoadFields().isEmpty()) { |
| 1236 | + cmdArgs.add("LOAD"); |
| 1237 | + cmdArgs.add(options.getLoadFields().size()); |
| 1238 | + cmdArgs.addAll(options.getLoadFields()); |
| 1239 | + } |
| 1240 | + |
| 1241 | + if (options.getGroupBy() != null) { |
| 1242 | + for (GroupBy groupBy : options.getGroupBy()) { |
| 1243 | + GroupParams groupParams = (GroupParams) groupBy; |
| 1244 | + cmdArgs.add("GROUPBY"); |
| 1245 | + cmdArgs.add(groupParams.getFieldNames().size()); |
| 1246 | + cmdArgs.addAll(groupParams.getFieldNames()); |
| 1247 | + if (groupParams.getReducers() != null) { |
| 1248 | + for (Reducer reducer : groupParams.getReducers()) { |
| 1249 | + ReducerParams reducerParams = (ReducerParams) reducer; |
| 1250 | + cmdArgs.add("REDUCE"); |
| 1251 | + cmdArgs.add(reducerParams.getFunctionName()); |
| 1252 | + cmdArgs.add(reducerParams.getArgs().size()); |
| 1253 | + if (!reducerParams.getArgs().isEmpty()) { |
| 1254 | + cmdArgs.addAll(reducerParams.getArgs()); |
| 1255 | + } |
| 1256 | + if (reducerParams.getAs() != null) { |
| 1257 | + cmdArgs.add("AS"); |
| 1258 | + cmdArgs.add(reducerParams.getAs()); |
| 1259 | + } |
| 1260 | + } |
| 1261 | + } |
| 1262 | + } |
| 1263 | + } |
| 1264 | + |
| 1265 | + if (options.getExpressions() != null) { |
| 1266 | + for (Expression expr : options.getExpressions()) { |
| 1267 | + cmdArgs.add("APPLY"); |
| 1268 | + cmdArgs.add(expr.getValue()); |
| 1269 | + cmdArgs.add("AS"); |
| 1270 | + cmdArgs.add(expr.getAs()); |
| 1271 | + } |
| 1272 | + } |
| 1273 | + |
| 1274 | + if (options.getPostFilter() != null) { |
| 1275 | + cmdArgs.add("FILTER"); |
| 1276 | + cmdArgs.add(options.getPostFilter()); |
| 1277 | + } |
| 1278 | + |
| 1279 | + if (options.getParams() != null && !options.getParams().isEmpty()) { |
| 1280 | + List<Object> paramsArgs = new ArrayList<>(); |
| 1281 | + for (Map.Entry<String, Object> entry : options.getParams().entrySet()) { |
| 1282 | + paramsArgs.add(entry.getKey()); |
| 1283 | + paramsArgs.add(entry.getValue()); |
| 1284 | + } |
| 1285 | + cmdArgs.add("PARAMS"); |
| 1286 | + cmdArgs.add(paramsArgs.size()); |
| 1287 | + cmdArgs.addAll(paramsArgs); |
| 1288 | + } |
| 1289 | + |
| 1290 | + if (options.getTimeout() != null) { |
| 1291 | + cmdArgs.add("TIMEOUT"); |
| 1292 | + cmdArgs.add(options.getTimeout().toMillis()); |
| 1293 | + } |
| 1294 | + |
| 1295 | + return commandExecutor.readAsync((String) null, codec, RedisCommands.HYBRID_SEARCH, cmdArgs.toArray()); |
| 1296 | + } |
1093 | 1297 | } |
0 commit comments