Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/server/generic_family.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,13 @@ OpResult<uint32_t> OpStore(const OpArgs& op_args, std::string_view key, Iterator
IteratorEnd&& end_it) {
uint32_t len = 0;

// If we are about to overwrite an existing indexed document (HASH/JSON),
// remove it from search indices first to avoid duplicate entries.
auto existing = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key).it;
if (IsValid(existing)) {
RemoveKeyFromIndexesIfNeeded(key, op_args.db_cntx, existing->second, op_args.shard);
}

QList* ql_v2 = CompactObj::AllocateMR<QList>();
QList::Where where = QList::TAIL;
for (auto it = start_it; it != end_it; ++it) {
Expand Down
24 changes: 24 additions & 0 deletions src/server/search/search_family_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2728,6 +2728,30 @@ TEST_F(SearchFamilyTest, SetDoesNotUpdateIndexesBug) {
EXPECT_THAT(resp, AreDocIds("k1"));
}

TEST_F(SearchFamilyTest, SortStoreDoesNotUpdateIndexesBug) {
// Create an index over HASH
auto resp = Run({"FT.CREATE", "index", "ON", "HASH", "SCHEMA", "field", "TEXT"});
EXPECT_THAT(resp, "OK");

// Index a HASH document under k1
resp = Run({"HSET", "k1", "field", "value"});
EXPECT_THAT(resp, IntArg(1));

// Prepare a source list to sort and store into k1 (overwriting k1 to LIST)
EXPECT_THAT(Run({"RPUSH", "lst", "b", "a"}), IntArg(2));
// SORT lst STORE k1 -> changes type of k1 from HASH to LIST
Run({"SORT", "lst", "ALPHA", "STORE", "k1"});

// Rename away and recreate k1 as HASH again
EXPECT_EQ(Run({"RENAME", "k1", "anotherkey"}), "OK");
EXPECT_THAT(Run({"HSET", "k1", "field", "value"}), IntArg(1));

// If SORT/STORE failed to remove k1 from indexes, the re-index here should crash.
// Successful run should contain only the new k1 document in the index.
resp = Run({"FT.SEARCH", "index", "*"});
EXPECT_THAT(resp, AreDocIds("k1"));
}

TEST_F(SearchFamilyTest, BlockSizeOptionFtCreate) {
// Create an index with a block size option
auto resp = Run({"FT.CREATE", "index", "ON", "HASH", "SCHEMA", "number1", "NUMERIC", "BLOCKSIZE",
Expand Down
Loading