From 4f1c7d992619a6ff048d84ba850fa6de28a7b72a Mon Sep 17 00:00:00 2001 From: is-a-gamer <48053608+is-a-gamer@users.noreply.github.com> Date: Fri, 18 Dec 2020 21:31:20 +0800 Subject: [PATCH] [add] added DropIndex method (#94) (#96) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [add] added DropIndex method * Included DropIndex() example. Extended method description * [add] Included extra test to cover all DropIndex() conditions Co-authored-by: 何鸿志 Co-authored-by: filipecosta90 --- redisearch/client.go | 18 ++++++++ redisearch/client_test.go | 71 +++++++++++++++++++++++++++++++ redisearch/example_client_test.go | 48 +++++++++++++++++++++ 3 files changed, 137 insertions(+) diff --git a/redisearch/client.go b/redisearch/client.go index 84d0a05..bc0ca3b 100644 --- a/redisearch/client.go +++ b/redisearch/client.go @@ -363,6 +363,24 @@ func (i *Client) Drop() error { } +// Deletes the secondary index and optionally the associated hashes +// +// Available since RediSearch 2.0. +// +// By default, DropIndex() which is a wrapper for RediSearch FT.DROPINDEX does not delete the document hashes associated with the index. +// Setting the argument deleteDocuments to true deletes the hashes as well. +func (i *Client) DropIndex(deleteDocuments bool) error { + conn := i.pool.Get() + defer conn.Close() + var err error = nil + if deleteDocuments { + _, err = conn.Do("FT.DROPINDEX", i.name, "DD") + } else { + _, err = conn.Do("FT.DROPINDEX", i.name) + } + return err +} + // Delete the document from the index, optionally delete the actual document // WARNING: As of RediSearch 2.0 and above, FT.DEL always deletes the underlying document. // Deprecated: This function is deprecated on RediSearch 2.0 and above, use DeleteDocument() instead diff --git a/redisearch/client_test.go b/redisearch/client_test.go index bf9044c..ab8dd7f 100644 --- a/redisearch/client_test.go +++ b/redisearch/client_test.go @@ -894,3 +894,74 @@ func TestClient_CreateIndex(t *testing.T) { assert.Equal(t, "Jon", docs[0].Properties["name"]) assert.Equal(t, "John", docs[1].Properties["name"]) } + +func TestClient_DropIndex(t *testing.T) { + c := createClient("drop-index-example") + version, err := c.getRediSearchVersion() + assert.Nil(t, err) + if version <= 10699 { + // DropIndex() is available for RediSearch 2.0+ + return + } + + // Create a schema + schema := NewSchema(DefaultOptions). + AddField(NewTextFieldOptions("name", TextFieldOptions{Sortable: true, PhoneticMatcher: PhoneticDoubleMetaphoneEnglish})). + AddField(NewNumericField("age")) + + // IndexDefinition is available for RediSearch 2.0+ + // In this example we will only index keys started by product: + indexDefinition := NewIndexDefinition().AddPrefix("drop-index:") + + // Add the Index Definition + err = c.CreateIndexWithIndexDefinition(schema, indexDefinition) + assert.Nil(t, err) + + // Create docs with a name that has the same phonetic matcher + vanillaConnection := c.pool.Get() + vanillaConnection.Do("HSET", "drop-index:doc1", "name", "Jon", "age", 25) + vanillaConnection.Do("HSET", "drop-index:doc2", "name", "John", "age", 20) + + // Wait for all documents to be indexed + info, _ := c.Info() + for info.IsIndexing { + time.Sleep(time.Second) + info, _ = c.Info() + } + + // Drop index but keep docs + err = c.DropIndex(false) + assert.Nil(t, err) + // Now that we don't have the index this should raise an error + _, err = c.Info() + assert.EqualError(t, err, "Unknown Index name") + // Assert hashes still exist + result, err := vanillaConnection.Do("EXISTS", "drop-index:doc1") + assert.Equal(t, int64(1), result) + result, err = vanillaConnection.Do("EXISTS", "drop-index:doc2") + assert.Equal(t, int64(1), result) + + // Create index again + err = c.CreateIndexWithIndexDefinition(schema, indexDefinition) + + // Wait for all documents to be indexed again + info, _ = c.Info() + for info.IsIndexing { + time.Sleep(time.Second) + info, _ = c.Info() + } + + assert.Nil(t, err) + // Drop index but keep docs + err = c.DropIndex(true) + assert.Nil(t, err) + // Now that we don't have the index this should raise an error + _, err = c.Info() + assert.EqualError(t, err, "Unknown Index name") + // Assert hashes still exist + result, err = vanillaConnection.Do("EXISTS", "drop-index:doc1") + assert.Equal(t, int64(0), result) + result, err = vanillaConnection.Do("EXISTS", "drop-index:doc2") + assert.Equal(t, int64(0), result) + +} diff --git a/redisearch/example_client_test.go b/redisearch/example_client_test.go index 0914437..db9ea3c 100644 --- a/redisearch/example_client_test.go +++ b/redisearch/example_client_test.go @@ -107,6 +107,54 @@ func ExampleClient_CreateIndexWithIndexDefinition() { fmt.Printf("Total documents containing \"description\": %d.\n", total) } +// The following example illustrates an index creation and deletion. +// By default, DropIndex() which is a wrapper for RediSearch FT.DROPINDEX does not delete the document hashes associated with the index. +// Setting the argument deleteDocuments to true deletes the hashes as well. +// Available since RediSearch 2.0 +func ExampleClient_DropIndex() { + + host := "localhost:6379" + password := "" + pool := &redis.Pool{Dial: func() (redis.Conn, error) { + return redis.Dial("tcp", host, redis.DialPassword(password)) + }} + c := redisearch.NewClientFromPool(pool, "products-from-hashes") + + // Create a schema + schema := redisearch.NewSchema(redisearch.DefaultOptions). + AddField(redisearch.NewTextFieldOptions("name", redisearch.TextFieldOptions{Sortable: true})). + AddField(redisearch.NewTextFieldOptions("description", redisearch.TextFieldOptions{Weight: 5.0, Sortable: true})). + AddField(redisearch.NewNumericField("price")) + + // IndexDefinition is available for RediSearch 2.0+ + // Create a index definition for automatic indexing on Hash updates. + // In this example we will only index keys started by product: + indexDefinition := redisearch.NewIndexDefinition().AddPrefix("product:") + + // Add the Index Definition + c.CreateIndexWithIndexDefinition(schema, indexDefinition) + + // Get a vanilla connection and create 100 hashes + vanillaConnection := pool.Get() + for productNumber := 0; productNumber < 100; productNumber++ { + vanillaConnection.Do("HSET", fmt.Sprintf("product:%d", productNumber), "name", fmt.Sprintf("product name %d", productNumber), "description", "product description", "price", 10.99) + } + + // Wait for all documents to be indexed + info, _ := c.Info() + for info.IsIndexing { + time.Sleep(time.Second) + info, _ = c.Info() + } + + // Delete Index and Documents + err := c.DropIndex(true) + if err != nil { + log.Fatal(err) + } + +} + // exemplifies the NewClientFromPool function func ExampleNewClientFromPool() { host := "localhost:6379"