Skip to content

Commit d31ea5f

Browse files
refactor: address comments
Signed-off-by: Stepan Bagritsevich <stefan@dragonflydb.io>
1 parent 37ad2ee commit d31ea5f

File tree

3 files changed

+38
-33
lines changed

3 files changed

+38
-33
lines changed

src/server/search/doc_index.cc

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,24 @@ std::pair<std::vector<FieldReference>, SortIndiciesFieldsList> PreprocessAggrega
9494
return {std::move(fields), {sort_indicies_aliases.begin(), sort_indicies_aliases.end()}};
9595
}
9696

97+
/* Separate fields into basic and sortable. The second vector contains flags indicating
98+
whether the field at the same index in the first vector is sortable or not. */
99+
std::pair<std::vector<FieldReference>, std::vector<bool>> GetBasicFields(
100+
absl::Span<const std::string_view> fields, const search::Schema& schema) {
101+
const size_t fields_count = fields.size();
102+
std::vector<bool> is_sortable_field(fields_count);
103+
std::vector<FieldReference> basic_fields;
104+
basic_fields.reserve(fields_count);
105+
for (size_t i = 0; i < fields_count; ++i) {
106+
bool is_sortable = IsSortableField(fields[i], schema);
107+
is_sortable_field[i] = is_sortable;
108+
if (!is_sortable) {
109+
basic_fields.emplace_back(fields[i]);
110+
}
111+
}
112+
return {std::move(basic_fields), std::move(is_sortable_field)};
113+
}
114+
97115
} // namespace
98116

99117
bool FieldReference::IsJsonPath(std::string_view name) {
@@ -497,19 +515,8 @@ join::Vector<join::OwnedEntry> ShardDocIndex::PreagregateDataForJoin(
497515
search::SearchAlgorithm* search_algo) const {
498516
auto search_results = search_algo->Search(&*indices_);
499517

500-
// First filter out sortable and non-sortable fields
501-
// We will load them in different ways
502518
const size_t fields_count = join_fields.size();
503-
std::vector<bool> is_sortable_field(fields_count);
504-
std::vector<FieldReference> basic_fields;
505-
basic_fields.reserve(fields_count);
506-
for (size_t i = 0; i < fields_count; ++i) {
507-
bool is_sortable = IsSortableField(join_fields[i], base_->schema);
508-
is_sortable_field[i] = is_sortable;
509-
if (!is_sortable) {
510-
basic_fields.emplace_back(join_fields[i]);
511-
}
512-
}
519+
const auto [basic_fields, is_sortable_field] = GetBasicFields(join_fields, base_->schema);
513520

514521
join::Vector<join::OwnedEntry> result;
515522
result.reserve(search_results.ids.size());
@@ -561,16 +568,7 @@ ShardDocIndex::FieldsValuesPerDocId ShardDocIndex::LoadKeysData(
561568
const OpArgs& op_args, const absl::flat_hash_set<search::DocId>& doc_ids,
562569
absl::Span<const std::string_view> fields_to_load) const {
563570
const size_t fields_count = fields_to_load.size();
564-
std::vector<bool> is_sortable_field(fields_count);
565-
std::vector<FieldReference> basic_fields;
566-
basic_fields.reserve(fields_count);
567-
for (size_t i = 0; i < fields_count; ++i) {
568-
bool is_sortable = IsSortableField(fields_to_load[i], base_->schema);
569-
is_sortable_field[i] = is_sortable;
570-
if (!is_sortable) {
571-
basic_fields.emplace_back(fields_to_load[i]);
572-
}
573-
}
571+
const auto [basic_fields, is_sortable_field] = GetBasicFields(fields_to_load, base_->schema);
574572

575573
FieldsValuesPerDocId result;
576574
result.reserve(doc_ids.size());

src/server/search/search_family.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <absl/strings/ascii.h>
1010
#include <absl/strings/match.h>
1111
#include <absl/strings/str_format.h>
12+
#include <absl/strings/str_split.h>
13+
#include <absl/strings/string_view.h>
1214

1315
#include <atomic>
1416
#include <variant>
@@ -443,12 +445,11 @@ ParseResult<aggregate::SortParams> ParseAggregatorSortParams(CmdArgParser* parse
443445
}
444446

445447
std::pair<std::string_view, std::string_view> Split(std::string_view s, char delim) {
446-
auto pos = s.find(delim);
447-
if (pos == std::string_view::npos)
448-
return {s, std::string_view{}};
449-
return {s.substr(0, pos), s.substr(pos + 1)};
448+
return absl::StrSplit(s, absl::MaxSplits(absl::ByChar(delim), 1));
450449
}
451450

451+
// Example: LOAD_FROM index AS alias num_conditions condition [condition ...] [QUERY query]
452+
// condition is in the form index.field=foreign_index.field or foreign_index.field=index.field
452453
ParseResult<AggregateParams::JoinParams> ParseAggregatorJoinParams(
453454
CmdArgParser* parser, absl::flat_hash_set<std::string>* known_indexes) {
454455
AggregateParams::JoinParams join_params;
@@ -459,11 +460,17 @@ ParseResult<AggregateParams::JoinParams> ParseAggregatorJoinParams(
459460
join_params.index_alias = join_params.index;
460461
}
461462

463+
if (known_indexes->contains(join_params.index_alias)) {
464+
return CreateSyntaxError(
465+
absl::StrCat("Duplicate index alias in LOAD_FROM: '", join_params.index_alias, "'"));
466+
}
467+
462468
// Validate index name
463469
known_indexes->insert(join_params.index_alias);
464470

465471
size_t num_fields = parser->Next<size_t>();
466472
join_params.conditions.reserve(num_fields);
473+
// Conditions are in the form index.field=foreign_index.field or foreign_index.field=index.field
467474
while (parser->HasNext() && num_fields > 0) {
468475
auto [left, right] = Split(parser->Next(), '=');
469476
auto [l_index, l_field] = Split(left, '.');
@@ -729,14 +736,8 @@ join::Vector<join::Vector<join::Entry>> MergePreaggregatedShardJoinData(
729736
join::Vector<join::JoinableValue> field_values;
730737
field_values.reserve(entry.second.size());
731738

732-
// We need to convert std::string to std::string_view
733739
auto insert_copy = [&field_values](const auto& field_value) {
734-
using T = std::decay_t<decltype(field_value)>;
735-
if constexpr (std::is_same_v<T, std::string>) {
736-
field_values.emplace_back(std::string_view{field_value});
737-
} else {
738-
field_values.emplace_back(field_value);
739-
}
740+
field_values.emplace_back(field_value);
740741
};
741742

742743
for (const auto& field_value : entry.second) {

src/server/search/search_family_test.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,6 +3091,12 @@ TEST_F(SearchFamilyTest, AggregateWithLoadFromSyntaxErrors) {
30913091
EXPECT_THAT(Run({"ft.aggregate", "idx1", "*", "LOAD", "4", "idx1.num1", "idx1.str1", "idx2.num2",
30923092
"idx2.str2", "LOAD_FROM", "idx2", "AS", "alias", "1", "alias.num2=idx1.num1"}),
30933093
ErrArg("Unknown index alias 'idx2' in the LOAD option. Field: 'num2'"));
3094+
3095+
// Test same index used multiple times
3096+
EXPECT_THAT(Run({"ft.aggregate", "idx1", "*", "LOAD", "4", "idx1.num1", "idx1.str1", "idx2.num2",
3097+
"idx2.str2", "LOAD_FROM", "idx2", "1", "idx2.num2=idx1.num1", "LOAD_FROM",
3098+
"idx2", "1", "idx2.str2=idx1.str1"}),
3099+
ErrArg("Duplicate index alias in LOAD_FROM: 'idx2'"));
30943100
}
30953101

30963102
} // namespace dfly

0 commit comments

Comments
 (0)