Meilisearch Demo
+
+ + Use this demo to verify that the sync between Appwrite Databases and + Meilisearch was successful. Search your Meilisearch index using the + input below. +
+diff --git a/ruby/sync_with_meilisearch/Gemfile b/ruby/sync_with_meilisearch/Gemfile new file mode 100644 index 00000000..cb866cfd --- /dev/null +++ b/ruby/sync_with_meilisearch/Gemfile @@ -0,0 +1,4 @@ +source "https://rubygems.org" + +gem 'appwrite' +gem 'meilisearch' diff --git a/ruby/sync_with_meilisearch/README.md b/ruby/sync_with_meilisearch/README.md new file mode 100644 index 00000000..607e7679 --- /dev/null +++ b/ruby/sync_with_meilisearch/README.md @@ -0,0 +1,106 @@ +# ⚡ Ruby Sync with Meilisearch Function + +Syncs documents in an Appwrite database collection to a Meilisearch index. + +## 🧰 Usage + +### GET / + +Returns HTML page where search can be performed to test the indexing. + +### POST / + +Triggers indexing of the Appwrite database collection to Meilisearch. + +**Response** + +Sample `204` Response: No content. + +## ⚙️ Configuration + +| Setting | Value | +| ----------------- | ---------------- | +| Runtime | Ruby (3.0) | +| Entrypoint | `lib/main.rb` | +| Build Commands | `bundle install` | +| Permissions | `any` | +| Timeout (Seconds) | 15 | + +## 🔒 Environment Variables + +### APPWRITE_API_KEY + +API Key to talk to Appwrite backend APIs. + +| Question | Answer | +| ------------- | -------------------------------------------------------------------------------------------------- | +| Required | Yes | +| Sample Value | `d1efb...aec35` | +| Documentation | [Appwrite: Getting Started for Server](https://appwrite.io/docs/getting-started-for-server#apiKey) | + +### APPWRITE_DATABASE_ID + +The ID of the Appwrite database that contains the collection to sync. + +| Question | Answer | +| ------------- | --------------------------------------------------------- | +| Required | Yes | +| Sample Value | `612a3...5b6c9` | +| Documentation | [Appwrite: Databases](https://appwrite.io/docs/databases) | + +### APPWRITE_COLLECTION_ID + +The ID of the collection in the Appwrite database to sync. + +| Question | Answer | +| ------------- | ------------------------------------------------------------- | +| Required | Yes | +| Sample Value | `7c3e8...2a9f1` | +| Documentation | [Appwrite: Collections](https://appwrite.io/docs/databases#collection) | + +### APPWRITE_ENDPOINT + +The URL endpoint of the Appwrite server. If not provided, it defaults to the Appwrite Cloud server: `https://cloud.appwrite.io/v1`. + +| Question | Answer | +| ------------ | ------------------------------ | +| Required | No | +| Sample Value | `https://cloud.appwrite.io/v1` | + +### MEILISEARCH_ENDPOINT + +The host URL of the Meilisearch server. + +| Question | Answer | +| ------------ | ----------------------- | +| Required | Yes | +| Sample Value | `http://127.0.0.1:7700` | + +### MEILISEARCH_ADMIN_API_KEY + +The admin API key for Meilisearch. + +| Question | Answer | +| ------------- | ------------------------------------------------------------------------ | +| Required | Yes | +| Sample Value | `masterKey1234` | +| Documentation | [Meilisearch: API Keys](https://docs.meilisearch.com/reference/api/keys) | + +### MEILISEARCH_INDEX_NAME + +Name of the Meilisearch index to which the documents will be synchronized. + +| Question | Answer | +| ------------ | ---------- | +| Required | Yes | +| Sample Value | `my_index` | + +### MEILISEARCH_SEARCH_API_KEY + +API Key for Meilisearch search operations. + +| Question | Answer | +| ------------- | ------------------------------------------------------------------------ | +| Required | Yes | +| Sample Value | `searchKey1234` | +| Documentation | [Meilisearch: API Keys](https://docs.meilisearch.com/reference/api/keys) | diff --git a/ruby/sync_with_meilisearch/lib/main.rb b/ruby/sync_with_meilisearch/lib/main.rb new file mode 100644 index 00000000..be5ebf8b --- /dev/null +++ b/ruby/sync_with_meilisearch/lib/main.rb @@ -0,0 +1,72 @@ +require 'appwrite' +require 'meilisearch' +require_relative 'utils' + +def main(context) + throw_if_missing(ENV, [ + 'APPWRITE_API_KEY', + 'APPWRITE_DATABASE_ID', + 'APPWRITE_COLLECTION_ID', + 'MEILISEARCH_ENDPOINT', + 'MEILISEARCH_INDEX_NAME', + 'MEILISEARCH_ADMIN_API_KEY', + 'MEILISEARCH_SEARCH_API_KEY' + ]) + + if context.req.method == 'GET' + html = interpolate(get_static_file('index.html'), { + 'MEILISEARCH_ENDPOINT' => ENV['MEILISEARCH_ENDPOINT'], + 'MEILISEARCH_INDEX_NAME' => ENV['MEILISEARCH_INDEX_NAME'], + 'MEILISEARCH_SEARCH_API_KEY' => ENV['MEILISEARCH_SEARCH_API_KEY'] + }) + + return context.res.send(html, 200, { 'Content-Type' => 'text/html; charset=utf-8' }) + end + + client = Appwrite::Client.new + client + .set_endpoint(ENV['APPWRITE_ENDPOINT'] || 'https://cloud.appwrite.io/v1') + .set_project(ENV['APPWRITE_FUNCTION_PROJECT_ID']) + .set_key(ENV['APPWRITE_API_KEY']) + + databases = Appwrite::Databases.new(client) + + meilisearch = MeiliSearch::Client.new(ENV['MEILISEARCH_ENDPOINT'], ENV['MEILISEARCH_ADMIN_API_KEY']) + + index_name = ENV['MEILISEARCH_INDEX_NAME'] + + database = Appwrite::Database.new(client) + + index = meilisearch.index(index_name) + + cursor = nil + + begin + queries = [Appwrite::Query.new.set_limit(100)] + + if cursor + queries.push(Appwrite::Query.new.set_cursor(cursor)) + end + + documents = database.list_documents( + ENV['APPWRITE_DATABASE_ID'], + ENV['APPWRITE_COLLECTION_ID'], + queries + ) + + if documents['documents'].length > 0 + cursor = documents['documents'].last['$id'] + else + context.error('No more documents found.') + cursor = nil + break + end + + context.log("Syncing chunk of #{documents['documents'].length} documents ...") + index.add_documents(documents['documents'], primary_key: '$id') + end while cursor + + context.log('Sync finished.') + + return context.res.send('Sync finished.', 200) +end \ No newline at end of file diff --git a/ruby/sync_with_meilisearch/lib/utils.rb b/ruby/sync_with_meilisearch/lib/utils.rb new file mode 100644 index 00000000..910707ec --- /dev/null +++ b/ruby/sync_with_meilisearch/lib/utils.rb @@ -0,0 +1,15 @@ +require 'pathname' + +def throw_if_missing(hash, keys) + missing = keys.select { |key| !hash.key?(key) || hash[key].nil? } + raise "Missing required fields: #{missing.join(', ')}" if missing.any? +end + +def get_static_file(file_name) + static_folder = File.join(File.dirname(__FILE__), '../static') + File.read(File.join(static_folder, file_name)) +end + +def interpolate(template, values) + template.gsub(/{{([^}]+)}}/) { |match| values[match[2..-3].strip] || match } +end diff --git a/ruby/sync_with_meilisearch/static/index.html b/ruby/sync_with_meilisearch/static/index.html new file mode 100644 index 00000000..7a7fc22e --- /dev/null +++ b/ruby/sync_with_meilisearch/static/index.html @@ -0,0 +1,72 @@ + + +
+ + + +
+ + Use this demo to verify that the sync between Appwrite Databases and + Meilisearch was successful. Search your Meilisearch index using the + input below. +
+