-
Notifications
You must be signed in to change notification settings - Fork 69
support for [TEMPORARY {seconds}] on FT.CREATE #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # Go parameters | ||
| GOCMD=go | ||
| GOBUILD=$(GOCMD) build | ||
| GOINSTALL=$(GOCMD) install | ||
| GOCLEAN=$(GOCMD) clean | ||
| GOTEST=$(GOCMD) test | ||
| GOGET=$(GOCMD) get | ||
| GOMOD=$(GOCMD) mod | ||
|
|
||
| .PHONY: all test coverage | ||
| all: test coverage | ||
|
|
||
| get: | ||
| $(GOGET) -t -v ./... | ||
|
|
||
| examples: get | ||
| $(GOBUILD) ./examples/quickstart/. | ||
| $(GOBUILD) ./examples/temporary/. | ||
| ./quickstart > /dev/null | ||
|
|
||
| test: get examples | ||
| $(GOTEST) -race -covermode=atomic ./... | ||
|
|
||
| coverage: get test | ||
| $(GOTEST) -race -coverprofile=coverage.txt -covermode=atomic ./redisearch | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "github.com/RediSearch/redisearch-go/redisearch" | ||
| "log" | ||
| "time" | ||
| ) | ||
|
|
||
| /** | ||
| * This demo should be updated in RediSearch.io if changed | ||
| * Update at: https://github.com/RediSearch/RediSearch/blob/master/docs/go_client.md | ||
| */ | ||
| func main() { | ||
| // Create a client. By default a client is schemaless | ||
| // unless a schema is provided when creating the index | ||
| c := redisearch.NewClient("localhost:6379", "myIndex") | ||
|
|
||
| // Create a schema | ||
| sc := redisearch.NewSchema(redisearch.DefaultOptions). | ||
| AddField(redisearch.NewTextField("body")). | ||
| AddField(redisearch.NewTextFieldOptions("title", redisearch.TextFieldOptions{Weight: 5.0, Sortable: true})). | ||
| AddField(redisearch.NewNumericField("date")) | ||
|
|
||
| // Drop an existing index. If the index does not exist an error is returned | ||
| c.Drop() | ||
|
|
||
| // Create the index with the given schema | ||
| if err := c.CreateIndex(sc); err != nil { | ||
| log.Fatal(err) | ||
| } | ||
|
|
||
| // Create a document with an id and given score | ||
| doc := redisearch.NewDocument("doc1", 1.0) | ||
| doc.Set("title", "Hello world"). | ||
| Set("body", "foo bar"). | ||
| Set("date", time.Now().Unix()) | ||
|
|
||
| // Index the document. The API accepts multiple documents at a time | ||
| if err := c.IndexOptions(redisearch.DefaultIndexingOptions, doc); err != nil { | ||
| log.Fatal(err) | ||
| } | ||
|
|
||
| // Searching with limit and sorting | ||
| docs, total, err := c.Search(redisearch.NewQuery("hello world"). | ||
| Limit(0, 2). | ||
| SetReturnFields("title")) | ||
|
|
||
| fmt.Println(docs[0].Id, docs[0].Properties["title"], total, err) | ||
| // Output: doc1 Hello world 1 <nil> | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "log" | ||
| "time" | ||
|
|
||
| "github.com/RediSearch/redisearch-go/redisearch" | ||
| ) | ||
|
|
||
| /** | ||
| * This demo demonstrates the usage of CreateIndex(), to create a lightweight temporary index that will expire after the specified period of inactivity. | ||
| * The internal idle timer is reset whenever the index is searched or added to. | ||
| * Because such indexes are lightweight, you can create thousands of such indexes without negative performance implications. | ||
| */ | ||
| func main() { | ||
| // Create a client. By default a client is schemaless | ||
| // unless a schema is provided when creating the index | ||
| c := redisearch.NewClient("localhost:6379", "myTemporaryIndex") | ||
|
|
||
| // Create a schema with a temporary index with temporary period of 10s | ||
| sc := redisearch.NewSchema(*redisearch.NewOptions().SetTemporaryPeriod(10)). | ||
| AddField(redisearch.NewTextField("body")). | ||
| AddField(redisearch.NewTextFieldOptions("title", redisearch.TextFieldOptions{Weight: 5.0, Sortable: true})). | ||
| AddField(redisearch.NewNumericField("date")) | ||
|
|
||
| // Drop an existing index. If the index does not exist an error is returned | ||
| c.Drop() | ||
|
|
||
| // Create the index with the given schema | ||
| if err := c.CreateIndex(sc); err != nil { | ||
| log.Fatal(err) | ||
| } | ||
|
|
||
| // Create a document with an id and given score | ||
| doc := redisearch.NewDocument("doc1", 1.0) | ||
| doc.Set("title", "Hello world"). | ||
| Set("body", "foo bar"). | ||
| Set("date", time.Now().Unix()) | ||
|
|
||
| // Index the document. The API accepts multiple documents at a time | ||
| if err := c.IndexOptions(redisearch.DefaultIndexingOptions, doc); err != nil { | ||
| log.Fatal(err) | ||
| } | ||
|
|
||
| docs, total, err := c.Search(redisearch.NewQuery("hello world"). | ||
| Limit(0, 2). | ||
| SetReturnFields("title")) | ||
|
|
||
| // Verify that the we're able to search on the temporary created index | ||
| fmt.Println(docs[0].Id, docs[0].Properties["title"], total, err) | ||
| // Output: doc1 Hello world 1 <nil> | ||
|
|
||
| time.Sleep(15*time.Second) | ||
| // Searching with limit and sorting | ||
| _, err = c.Info() | ||
| fmt.Println(err) | ||
| // Output: Unknown Index name | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| package redisearch_test | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "github.com/RediSearch/redisearch-go/redisearch" | ||
| "log" | ||
| "time" | ||
| ) | ||
|
|
||
| // exemplifies the CreateIndex function with a temporary index specification | ||
| func ExampleCreateIndex_temporary() { | ||
| // Create a client. By default a client is schemaless | ||
| // unless a schema is provided when creating the index | ||
| c := redisearch.NewClient("localhost:6379", "myTemporaryIndex") | ||
|
|
||
| // Create a schema with a temporary period of 60seconds | ||
| sc := redisearch.NewSchema(*redisearch.NewOptions().SetTemporaryPeriod(10)). | ||
| AddField(redisearch.NewTextField("body")). | ||
| AddField(redisearch.NewTextFieldOptions("title", redisearch.TextFieldOptions{Weight: 5.0, Sortable: true})). | ||
| AddField(redisearch.NewNumericField("date")) | ||
|
|
||
| // Create the index with the given schema | ||
| if err := c.CreateIndex(sc); err != nil { | ||
| log.Fatal(err) | ||
| } | ||
|
|
||
| // Create a document with an id and given score | ||
| doc := redisearch.NewDocument("doc1", 1.0) | ||
| doc.Set("title", "Hello world"). | ||
| Set("body", "foo bar"). | ||
| Set("date", time.Now().Unix()) | ||
|
|
||
| // Index the document. The API accepts multiple documents at a time | ||
| if err := c.IndexOptions(redisearch.DefaultIndexingOptions, doc); err != nil { | ||
| log.Fatal(err) | ||
| } | ||
|
|
||
| docs, total, err := c.Search(redisearch.NewQuery("hello world"). | ||
| Limit(0, 2). | ||
| SetReturnFields("title")) | ||
|
|
||
| // Verify that the we're able to search on the temporary created index | ||
| fmt.Println(docs[0].Id, docs[0].Properties["title"], total, err) | ||
|
|
||
| time.Sleep(15 * time.Second) | ||
| // Searching with limit and sorting | ||
| _, err = c.Info() | ||
| fmt.Println(err) | ||
| // Output: doc1 Hello world 1 <nil> | ||
| // Unknown Index name | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,42 @@ type Options struct { | |
| // If the list is nil the default stop-words list is used. | ||
| // See https://oss.redislabs.com/redisearch/Stopwords.html#default_stop-word_list | ||
| Stopwords []string | ||
|
|
||
| // If set to true, creates a lightweight temporary index which will expire after the specified period of inactivity. | ||
| // The internal idle timer is reset whenever the index is searched or added to. | ||
| // Because such indexes are lightweight, you can create thousands of such indexes without negative performance implications. | ||
| Temporary bool | ||
| TemporaryPeriod int | ||
| } | ||
|
|
||
| func NewOptions() *Options { | ||
| var opts = DefaultOptions | ||
| return &opts | ||
| } | ||
|
|
||
| // If set to true, creates a lightweight temporary index which will expire after the specified period of inactivity. | ||
| // The internal idle timer is reset whenever the index is searched or added to. | ||
| // To enable the temporary index creation, use SetTemporaryPeriod(). This method should be preferably used for disabling the flag | ||
| func (options *Options) SetTemporary(temporary bool) *Options { | ||
| options.Temporary = temporary | ||
| return options | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure someone will create a temporary object and then regret ... but it's ok to have this api I guess.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe it makes sense if you want to reuse options across several creations. WDYT? |
||
| } | ||
|
|
||
| // If set to a positive integer, creates a lightweight temporary index which will expire after the specified period of inactivity (in seconds). | ||
| // The internal idle timer is reset whenever the index is searched or added to. | ||
| func (options *Options) SetTemporaryPeriod(period int) *Options { | ||
| options.TemporaryPeriod = period | ||
| options.Temporary = true | ||
| return options | ||
| } | ||
|
|
||
| // Set the index with a custom stop-words list, to be ignored during indexing and search time | ||
| // This is an option that is applied and index level. | ||
| // If the list is nil the default stop-words list is used. | ||
| // See https://oss.redislabs.com/redisearch/Stopwords.html#default_stop-word_list | ||
| func (options *Options) SetStopWords(stopwords []string) *Options { | ||
| options.Stopwords = stopwords | ||
| return options | ||
| } | ||
|
|
||
| // DefaultOptions represents the default options | ||
|
|
@@ -44,6 +80,8 @@ var DefaultOptions = Options{ | |
| NoFrequencies: false, | ||
| NoOffsetVectors: false, | ||
| Stopwords: nil, | ||
| Temporary: false, | ||
| TemporaryPeriod: 0, | ||
| } | ||
|
|
||
| const ( | ||
|
|
@@ -204,15 +242,19 @@ func (m *Schema) AddField(f Field) *Schema { | |
|
|
||
| func SerializeSchema(s *Schema, args redis.Args) (argsOut redis.Args, err error) { | ||
| argsOut = args | ||
| if s.Options.NoOffsetVectors { | ||
| argsOut = append(argsOut, "NOOFFSETS") | ||
| } | ||
| if s.Options.Temporary { | ||
| argsOut = append(argsOut, "TEMPORARY",s.Options.TemporaryPeriod) | ||
| } | ||
| if s.Options.NoFieldFlags { | ||
| argsOut = append(argsOut, "NOFIELDS") | ||
| } | ||
| if s.Options.NoFrequencies { | ||
| argsOut = append(argsOut, "NOFREQS") | ||
| } | ||
| if s.Options.NoOffsetVectors { | ||
| argsOut = append(argsOut, "NOOFFSETS") | ||
| } | ||
|
|
||
| if s.Options.Stopwords != nil { | ||
| argsOut = argsOut.Add("STOPWORDS", len(s.Options.Stopwords)) | ||
| if len(s.Options.Stopwords) > 0 { | ||
|
|
@@ -224,7 +266,7 @@ func SerializeSchema(s *Schema, args redis.Args) (argsOut redis.Args, err error) | |
| for _, f := range s.Fields { | ||
| argsOut, err = serializeField(f, argsOut) | ||
| if err != nil { | ||
| return nil,err | ||
| return nil, err | ||
| } | ||
| } | ||
| return | ||
|
|
@@ -300,7 +342,7 @@ func serializeField(f Field, args redis.Args) (argsOut redis.Args, err error) { | |
| } | ||
| } | ||
| default: | ||
| err = fmt.Errorf("Unrecognized field type %v serialization", f.Type ) | ||
| err = fmt.Errorf("Unrecognized field type %v serialization", f.Type) | ||
| return | ||
| } | ||
| return | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it common on go project to have a Makefile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I knew someone would pick on the GOCMD =)
regarding the makefile I believe it helps both for developing, manual testing and CI. cc @rafie