typesense 0.1.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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