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
2 changes: 1 addition & 1 deletion src/server/search/doc_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct DocIndex {

struct DocIndexInfo {
DocIndex base_index;
size_t num_docs;
size_t num_docs = 0;

// Build original ft.create command that can be used to re-create this index
std::string BuildRestoreCommand() const;
Expand Down
54 changes: 54 additions & 0 deletions src/server/search/search_family.cc
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,59 @@ void SearchFamily::FtCreate(CmdArgList args, ConnectionContext* cntx) {
cntx->SendOk();
}

void SearchFamily::FtAlter(CmdArgList args, ConnectionContext* cntx) {
CmdArgParser parser{args};
string_view idx_name = parser.Next();
parser.ExpectTag("SCHEMA");
parser.ExpectTag("ADD");

if (auto err = parser.Error(); err)
return cntx->SendError(err->MakeReply());

// First, extract existing index info
shared_ptr<DocIndex> index_info;
auto idx_cb = [idx_name, &index_info](auto* tx, EngineShard* es) {
if (es->shard_id() > 0) // all shards have the same data, fetch from first
return OpStatus::OK;

if (auto* idx = es->search_indices()->GetIndex(idx_name); idx != nullptr)
index_info = make_shared<DocIndex>(idx->GetInfo().base_index);
return OpStatus::OK;
};
cntx->transaction->Execute(idx_cb, false);

if (!index_info) {
cntx->transaction->Conclude();
return cntx->SendError("Index not found");
}

// Parse additional schema
optional<search::Schema> new_fields = ParseSchemaOrReply(index_info->type, parser, cntx);
if (!new_fields) {
cntx->transaction->Conclude();
return;
}

LOG(INFO) << "Adding "
<< DocIndexInfo{.base_index = DocIndex{.schema = *new_fields}}.BuildRestoreCommand();

// Merge schemas
search::Schema& schema = index_info->schema;
schema.fields.insert(new_fields->fields.begin(), new_fields->fields.end());
schema.field_names.insert(new_fields->field_names.begin(), new_fields->field_names.end());

// Rebuild index
// TODO: Introduce partial rebuild
auto upd_cb = [idx_name, index_info](Transaction* tx, EngineShard* es) {
es->search_indices()->DropIndex(idx_name);
es->search_indices()->InitIndex(tx->GetOpArgs(es), idx_name, index_info);
return OpStatus::OK;
};
cntx->transaction->Execute(upd_cb, true);
Comment on lines +514 to +520
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it's not that difficult... is it worth it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not now


cntx->SendOk();
}

void SearchFamily::FtDropIndex(CmdArgList args, ConnectionContext* cntx) {
string_view idx_name = ArgS(args, 0);
// TODO: Handle optional DD param
Expand Down Expand Up @@ -753,6 +806,7 @@ void SearchFamily::Register(CommandRegistry* registry) {
registry->StartFamily();
*registry << CI{"FT.CREATE", CO::WRITE | CO::GLOBAL_TRANS, -2, 0, 0, acl::FT_SEARCH}.HFUNC(
FtCreate)
<< CI{"FT.ALTER", CO::WRITE | CO::GLOBAL_TRANS, -3, 0, 0, acl::FT_SEARCH}.HFUNC(FtAlter)
<< CI{"FT.DROPINDEX", CO::WRITE | CO::GLOBAL_TRANS, -2, 0, 0, acl::FT_SEARCH}.HFUNC(
FtDropIndex)
<< CI{"FT.INFO", kReadOnlyMask, 2, 0, 0, acl::FT_SEARCH}.HFUNC(FtInfo)
Expand Down
1 change: 1 addition & 0 deletions src/server/search/search_family.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ConnectionContext;

class SearchFamily {
static void FtCreate(CmdArgList args, ConnectionContext* cntx);
static void FtAlter(CmdArgList args, ConnectionContext* cntx);
static void FtDropIndex(CmdArgList args, ConnectionContext* cntx);
static void FtInfo(CmdArgList args, ConnectionContext* cntx);
static void FtList(CmdArgList args, ConnectionContext* cntx);
Expand Down
18 changes: 18 additions & 0 deletions src/server/search/search_family_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,24 @@ TEST_F(SearchFamilyTest, CreateDropListIndex) {
EXPECT_EQ(Run({"ft._list"}), "idx-3");
}

TEST_F(SearchFamilyTest, AlterIndex) {
Run({"hset", "d:1", "color", "blue", "cost", "150"});
Run({"hset", "d:2", "color", "green", "cost", "200"});

Run({"ft.create", "idx-1", "ON", "HASH"});

EXPECT_EQ(Run({"ft.alter", "idx-1", "schema", "add", "color", "tag"}), "OK");
EXPECT_THAT(Run({"ft.search", "idx-1", "@color:{blue}"}), AreDocIds("d:1"));
EXPECT_THAT(Run({"ft.search", "idx-1", "@color:{green}"}), AreDocIds("d:2"));

EXPECT_EQ(Run({"ft.alter", "idx-1", "schema", "add", "cost", "numeric"}), "OK");
EXPECT_THAT(Run({"ft.search", "idx-1", "@cost:[0 100]"}), kNoResults);
EXPECT_THAT(Run({"ft.search", "idx-1", "@cost:[100 300]"}), AreDocIds("d:1", "d:2"));

EXPECT_THAT(Run({"ft.alter", "idx-2", "schema", "add", "price", "numeric"}),
ErrArg("Index not found"));
}

TEST_F(SearchFamilyTest, InfoIndex) {
EXPECT_EQ(
Run({"ft.create", "idx-1", "ON", "HASH", "PREFIX", "1", "doc-", "SCHEMA", "name", "TEXT"}),
Expand Down