typesense 0.1.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/typesense'
4
+ require 'awesome_print'
5
+
6
+ AwesomePrint.defaults = {
7
+ indent: -2
8
+ }
9
+
10
+ ##
11
+ ## Setup
12
+ #
13
+ ### Option 1: Start a single-node cluster
14
+ # $ docker run -i -p 8108:8108 -v/tmp/typesense-server-data-1b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 8108 --enable-cors
15
+ #
16
+ ### Option 2: Start a 3-node cluster
17
+ #
18
+ # Create file in present working directory called typesense-server-peers (update IP Addresses appropriately to your local network):
19
+ # $ echo '172.17.0.2:8107:8108,172.17.0.3:7107:7108,172.17.0.4:9107:9108' > `pwd`/typesense-server-peers
20
+ #
21
+ # Start node 1:
22
+ # $ docker run -i -p 8108:8108 -p 8107:8107 -v/tmp/typesense-server-data-1b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 8108 --peering-port 8107 --enable-cors --nodes=/typesense-server-peers
23
+ #
24
+ # Start node 2:
25
+ # $ docker run -i -p 7108:7108 -p 7107:7107 -v/tmp/.typesense-server-data-2b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 7108 --peering-port 7107 --enable-cors --nodes=/typesense-server-peers
26
+ #
27
+ # Start node 3:
28
+ # $ docker run -i -p 9108:9108 -p 9107:9107 -v/tmp/.typesense-server-data-3b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 9108 --peering-port 9107 --enable-cors --nodes=/typesense-server-peers
29
+ #
30
+ # Note: Be sure to add `--license-key=<>` at the end when starting a Typesense Premium server
31
+
32
+ ##
33
+ # Create a client
34
+ @typesense = Typesense::Client.new(
35
+ nodes: [
36
+ {
37
+ host: 'localhost',
38
+ port: 8108,
39
+ protocol: 'http'
40
+ },
41
+ # Uncomment if starting a 3-node cluster, using Option 2 under Setup instructions above
42
+ {
43
+ host: 'localhost',
44
+ port: 7108,
45
+ protocol: 'http'
46
+ },
47
+ {
48
+ host: 'localhost',
49
+ port: 9108,
50
+ protocol: 'http'
51
+ }
52
+ ],
53
+ # If this optional key is specified, requests are always sent to this node first if it is healthy
54
+ # before falling back on the nodes mentioned in the `nodes` key. This is useful when running a distributed set of search clusters.
55
+ 'nearest_node': {
56
+ 'host': 'localhost',
57
+ 'port': '8108',
58
+ 'protocol': 'http'
59
+ },
60
+ api_key: 'xyz',
61
+ num_retries: 10,
62
+ healthcheck_interval_seconds: 1,
63
+ retry_interval_seconds: 0.01,
64
+ connection_timeout_seconds: 10,
65
+ logger: Logger.new(STDOUT),
66
+ log_level: Logger::DEBUG
67
+ )
@@ -4,65 +4,37 @@
4
4
  # These examples walk you through all the operations you can do on a collection and a document
5
5
  # Search is specifically covered in another file in the examples folder
6
6
 
7
- require_relative '../lib/typesense'
8
- require 'awesome_print'
9
-
10
- AwesomePrint.defaults = {
11
- indent: -2
12
- }
13
-
14
- ##
15
- # Setup
16
- #
17
- # Start the master
18
- # $ docker run -p 8108:8108 -it -v/tmp/typesense-data-master/:/data -it typesense/typesense:0.8.0-rc1 --data-dir /data --api-key=abcd --listen-port 8108
19
- #
20
- # Start the read replica
21
- # $ docker run -p 8109:8109 -it -v/tmp/typesense-data-read-replica-1/:/data -it typesense/typesense:0.8.0-rc1 --data-dir /data --api-key=wxyz --listen-port 8109 --master http://localhost:8108
22
-
23
- ##
24
- # Create a client
25
- typesense = Typesense::Client.new(
26
- master_node: {
27
- host: 'localhost',
28
- port: 8108,
29
- protocol: 'http',
30
- api_key: 'abcd'
31
- },
32
- read_replica_nodes: [
33
- {
34
- host: 'localhost',
35
- port: 8109,
36
- protocol: 'http',
37
- api_key: 'wxyz'
38
- }
39
- ],
40
- timeout_seconds: 10
41
- )
7
+ require_relative './client_initialization'
42
8
 
43
9
  ##
44
10
  # Create a collection
45
11
  schema = {
46
- 'name' => 'companies',
47
- 'fields' => [
12
+ 'name' => 'companies',
13
+ 'fields' => [
48
14
  {
49
15
  'name' => 'company_name',
50
16
  'type' => 'string'
51
17
  },
52
18
  {
53
- 'name' => 'num_employees',
54
- 'type' => 'int32'
19
+ 'name' => 'num_employees',
20
+ 'type' => 'int32'
55
21
  },
56
22
  {
57
- 'name' => 'country',
58
- 'type' => 'string',
23
+ 'name' => 'country',
24
+ 'type' => 'string',
59
25
  'facet' => true
60
26
  }
61
27
  ],
62
28
  'default_sorting_field' => 'num_employees'
63
29
  }
64
30
 
65
- collection = typesense.collections.create(schema)
31
+ # Delete the collection if it already exists
32
+ begin
33
+ @typesense.collections['companies'].delete
34
+ rescue Typesense::Error::ObjectNotFound
35
+ end
36
+
37
+ collection = @typesense.collections.create(schema)
66
38
  ap collection
67
39
 
68
40
  # {
@@ -87,7 +59,8 @@ ap collection
87
59
 
88
60
  ##
89
61
  # Retrieve a collection
90
- collection = typesense.collections['companies'].retrieve
62
+ sleep 0.5 # Give Typesense cluster a few hundred ms to create the collection on all nodes, before reading it right after (eventually consistent)
63
+ collection = @typesense.collections['companies'].retrieve
91
64
  ap collection
92
65
 
93
66
  # {
@@ -115,7 +88,7 @@ ap collection
115
88
 
116
89
  ##
117
90
  # Retrieve all collections
118
- collections = typesense.collections.retrieve
91
+ collections = @typesense.collections.retrieve
119
92
  ap collections
120
93
 
121
94
  # [
@@ -146,7 +119,7 @@ ap collections
146
119
  ##
147
120
  # Delete a collection
148
121
  # Deletion returns the schema of the collection after deletion
149
- collection = typesense.collections['companies'].delete
122
+ collection = @typesense.collections['companies'].delete
150
123
  ap collection
151
124
 
152
125
  # {
@@ -173,18 +146,18 @@ ap collection
173
146
  # }
174
147
 
175
148
  # Let's create the collection again for use in our remaining examples
176
- typesense.collections.create(schema)
149
+ @typesense.collections.create(schema)
177
150
 
178
151
  ##
179
152
  # Create (index) a document
180
153
  document = {
181
- 'id' => '124',
182
- 'company_name' => 'Stark Industries',
154
+ 'id' => '124',
155
+ 'company_name' => 'Stark Industries',
183
156
  'num_employees' => 5215,
184
- 'country' => 'USA'
157
+ 'country' => 'USA'
185
158
  }
186
159
 
187
- document = typesense.collections['companies'].documents.create(document)
160
+ document = @typesense.collections['companies'].documents.create(document)
188
161
  ap document
189
162
 
190
163
  # {
@@ -196,7 +169,8 @@ ap document
196
169
 
197
170
  ##
198
171
  # Retrieve a document
199
- document = typesense.collections['companies'].documents['124'].retrieve
172
+ sleep 0.5 # Give Typesense cluster a few hundred ms to create the document on all nodes, before reading it right after (eventually consistent)
173
+ document = @typesense.collections['companies'].documents['124'].retrieve
200
174
  ap document
201
175
 
202
176
  # {
@@ -209,7 +183,7 @@ ap document
209
183
  ##
210
184
  # Delete a document
211
185
  # Deleting a document, returns the document after deletion
212
- document = typesense.collections['companies'].documents['124'].delete
186
+ document = @typesense.collections['companies'].documents['124'].delete
213
187
  ap document
214
188
 
215
189
  # {
@@ -219,25 +193,28 @@ ap document
219
193
  # "num_employees" => 5215
220
194
  # }
221
195
 
222
- # Let's create two documents again for use in our remaining examples
223
- typesense.collections['companies'].documents.create(
224
- 'id' => '124',
225
- 'company_name' => 'Stark Industries',
226
- 'num_employees' => 5215,
227
- 'country' => 'USA'
228
- )
229
-
230
- typesense.collections['companies'].documents.create(
231
- 'id' => '125',
232
- 'company_name' => 'Acme Corp',
233
- 'num_employees' => 1002,
234
- 'country' => 'France'
235
- )
196
+ # Let's bulk create two documents again for use in our remaining examples
197
+ documents = [
198
+ {
199
+ 'id' => '124',
200
+ 'company_name' => 'Stark Industries',
201
+ 'num_employees' => 5215,
202
+ 'country' => 'USA'
203
+ },
204
+ {
205
+ 'id' => '125',
206
+ 'company_name' => 'Acme Corp',
207
+ 'num_employees' => 1002,
208
+ 'country' => 'France'
209
+ }
210
+ ]
211
+ ap @typesense.collections['companies'].documents.create_many(documents)
236
212
 
237
213
  ##
238
214
  # Export all documents in a collection in JSON Lines format
239
215
  # We use JSON Lines format for performance reasons. You can choose to parse selected lines (elements in the array) as needed.
240
- array_of_json_strings = typesense.collections['companies'].documents.export
216
+ sleep 0.5 # Give Typesense cluster a few hundred ms to create the document on all nodes, before reading it right after (eventually consistent)
217
+ array_of_json_strings = @typesense.collections['companies'].documents.export
241
218
  ap array_of_json_strings
242
219
 
243
220
  # [
@@ -248,4 +225,4 @@ ap array_of_json_strings
248
225
  ##
249
226
  # Cleanup
250
227
  # Drop the collection
251
- typesense.collections['companies'].delete
228
+ @typesense.collections['companies'].delete
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # These examples walk you through operations to manage API Keys
5
+
6
+ require_relative './client_initialization'
7
+
8
+ # Let's setup some test data for this example
9
+ schema = {
10
+ 'name' => 'users',
11
+ 'fields' => [
12
+ {
13
+ 'name' => 'company_id',
14
+ 'type' => 'int32',
15
+ 'facet' => false
16
+ },
17
+ {
18
+ 'name' => 'user_name',
19
+ 'type' => 'string',
20
+ 'facet' => false
21
+ },
22
+ {
23
+ 'name' => 'login_count',
24
+ 'type' => 'int32',
25
+ 'facet' => false
26
+ },
27
+ {
28
+ 'name' => 'country',
29
+ 'type' => 'string',
30
+ 'facet' => true
31
+ }
32
+ ],
33
+ 'default_sorting_field' => 'company_id'
34
+ }
35
+
36
+ # We have four users, belonging to two companies: 124 and 126
37
+ documents = [
38
+ {
39
+ 'company_id' => 124,
40
+ 'user_name' => 'Hilary Bradford',
41
+ 'login_count' => 10,
42
+ 'country' => 'USA'
43
+ },
44
+ {
45
+ 'company_id' => 124,
46
+ 'user_name' => 'Nile Carty',
47
+ 'login_count' => 100,
48
+ 'country' => 'USA'
49
+ },
50
+ {
51
+ 'company_id' => 126,
52
+ 'user_name' => 'Tahlia Maxwell',
53
+ 'login_count' => 1,
54
+ 'country' => 'France'
55
+ },
56
+ {
57
+ 'company_id' => 126,
58
+ 'user_name' => 'Karl Roy',
59
+ 'login_count' => 2,
60
+ 'country' => 'Germany'
61
+ }
62
+ ]
63
+
64
+ # Delete if the collection already exists from a previous example run
65
+ begin
66
+ @typesense.collections['users'].delete
67
+ rescue Typesense::Error::ObjectNotFound
68
+ end
69
+
70
+ # create a collection
71
+ @typesense.collections.create(schema)
72
+
73
+ # Index documents
74
+ documents.each do |document|
75
+ @typesense.collections['users'].documents.create(document)
76
+ end
77
+
78
+ # Generate an API key and restrict it to only allow searches
79
+ # You want to use this API Key in the browser instead of the master API Key
80
+ unscoped_search_only_api_key_response = @typesense.keys.create({
81
+ 'description' => 'Search-only key.',
82
+ 'actions' => ['documents:search'],
83
+ 'collections' => ['*']
84
+ })
85
+ ap unscoped_search_only_api_key_response
86
+
87
+ # Save the key returned, since this will be the only time the full API Key is returned, for security purposes
88
+ unscoped_search_only_api_key = unscoped_search_only_api_key_response['value']
89
+
90
+ # Side note: you can also retrieve metadata of API keys using the ID returned in the above response
91
+ unscoped_search_only_api_key_response = @typesense.keys[unscoped_search_only_api_key_response['id']].retrieve
92
+ ap unscoped_search_only_api_key_response
93
+
94
+ # We'll now use this search-only API key to generate a scoped search API key that can only access documents that have company_id:124
95
+ # This is useful when you store multi-tenant data in a single Typesense server, but you only want
96
+ # a particular tenant to access their own data. You'd generate one scoped search key per tenant.
97
+ # IMPORTANT: scoped search keys should only be generated *server-side*, so as to not leak the unscoped main search key to clients
98
+ scoped_search_only_api_key = @typesense.keys.generate_scoped_search_key(unscoped_search_only_api_key, { 'filter_by': 'company_id:124' })
99
+ ap "scoped_search_only_api_key: #{scoped_search_only_api_key}"
100
+
101
+ # Now let's search the data using the scoped API Key for company_id:124
102
+ # You can do searches with this scoped_search_only_api_key from the server-side or client-side
103
+ scoped_typesense_client = Typesense::Client.new({
104
+ 'nodes': [{
105
+ 'host': 'localhost',
106
+ 'port': '8108',
107
+ 'protocol': 'http'
108
+ }],
109
+ 'api_key': scoped_search_only_api_key
110
+ })
111
+
112
+ search_results = scoped_typesense_client.collections['users'].documents.search({
113
+ 'q' => 'Hilary',
114
+ 'query_by' => 'user_name'
115
+ })
116
+ ap search_results
117
+
118
+ # Search for a user that exists, but is outside the current key's scope
119
+ search_results = scoped_typesense_client.collections['users'].documents.search({
120
+ 'q': 'Maxwell',
121
+ 'query_by': 'user_name'
122
+ })
123
+ ap search_results # Will return empty result set
124
+
125
+ # Now let's delete the unscoped_search_only_api_key. You'd want to do this when you need to rotate keys for example.
126
+ results = @typesense.keys[unscoped_search_only_api_key_response['id']].delete
127
+ ap results
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # These examples walk you through operations specifically related to overrides
5
+ # This is a Typesense Premium feature (see: https://typesense.org/premium)
6
+ # Be sure to add `--license-key=<>` as a parameter, when starting a Typesense Premium server
7
+
8
+ require_relative './client_initialization'
9
+
10
+ ##
11
+ # Create a collection
12
+ schema = {
13
+ 'name' => 'companies',
14
+ 'fields' => [
15
+ {
16
+ 'name' => 'company_name',
17
+ 'type' => 'string'
18
+ },
19
+ {
20
+ 'name' => 'num_employees',
21
+ 'type' => 'int32'
22
+ },
23
+ {
24
+ 'name' => 'country',
25
+ 'type' => 'string',
26
+ 'facet' => true
27
+ }
28
+ ],
29
+ 'default_sorting_field' => 'num_employees'
30
+ }
31
+
32
+ @typesense.collections.create(schema)
33
+
34
+ # Let's create a couple documents for us to use in our search examples
35
+ @typesense.collections['companies'].documents.create(
36
+ 'id' => '124',
37
+ 'company_name' => 'Stark Industries',
38
+ 'num_employees' => 5215,
39
+ 'country' => 'USA'
40
+ )
41
+
42
+ @typesense.collections['companies'].documents.create(
43
+ 'id' => '127',
44
+ 'company_name' => 'Stark Corp',
45
+ 'num_employees' => 1031,
46
+ 'country' => 'USA'
47
+ )
48
+
49
+ @typesense.collections['companies'].documents.create(
50
+ 'id' => '125',
51
+ 'company_name' => 'Acme Corp',
52
+ 'num_employees' => 1002,
53
+ 'country' => 'France'
54
+ )
55
+
56
+ @typesense.collections['companies'].documents.create(
57
+ 'id' => '126',
58
+ 'company_name' => 'Doofenshmirtz Inc',
59
+ 'num_employees' => 2,
60
+ 'country' => 'Tri-State Area'
61
+ )
62
+
63
+ ##
64
+ # Create overrides
65
+
66
+ @typesense.collections['companies'].overrides.create(
67
+ "id": 'promote-doofenshmirtz',
68
+ "rule": {
69
+ "query": 'doofen',
70
+ "match": 'exact'
71
+ },
72
+ "includes": [{ 'id' => '126', 'position' => 1 }]
73
+ )
74
+ @typesense.collections['companies'].overrides.create(
75
+ "id": 'promote-acme',
76
+ "rule": {
77
+ "query": 'stark',
78
+ "match": 'exact'
79
+ },
80
+ "includes": [{ 'id' => '125', 'position' => 1 }]
81
+ )
82
+
83
+ ##
84
+ # Search for documents
85
+ results = @typesense.collections['companies'].documents.search(
86
+ 'q' => 'doofen',
87
+ 'query_by' => 'company_name'
88
+ )
89
+ ap results
90
+
91
+ results = @typesense.collections['companies'].documents.search(
92
+ 'q' => 'stark',
93
+ 'query_by' => 'company_name'
94
+ )
95
+ ap results
96
+
97
+ results = @typesense.collections['companies'].documents.search(
98
+ 'q' => 'Inc',
99
+ 'query_by' => 'company_name',
100
+ 'filter_by' => 'num_employees:<100',
101
+ 'sort_by' => 'num_employees:desc'
102
+ )
103
+ ap results
104
+
105
+ ##
106
+ # Cleanup
107
+ # Drop the collection
108
+ @typesense.collections['companies'].delete