Coder Social home page Coder Social logo

meilisearch-ruby's Introduction

Meilisearch-Ruby

Meilisearch Ruby

Latest Stable Version Test License Bors enabled

⚑ The Meilisearch API client written for Ruby πŸ’Ž

Meilisearch Ruby is the Meilisearch API client for Ruby developers.

Meilisearch is an open-source search engine. Learn more about Meilisearch.

Table of Contents

πŸ“– Documentation

This readme contains all the documentation you need to start using this Meilisearch SDK.

For general information on how to use Meilisearchβ€”such as our API reference, tutorials, guides, and in-depth articlesβ€”refer to our main documentation website.

⚑ Supercharge your Meilisearch experience

Say goodbye to server deployment and manual updates with Meilisearch Cloud. Get started with a 14-day free trial! No credit card required.

πŸ”§ Installation

This package requires Ruby version 3.0.0 or later.

With gem in command line:

gem install meilisearch

In your Gemfile with bundler:

source 'https://rubygems.org'

gem 'meilisearch'

Run Meilisearch

There are many easy ways to download and run a Meilisearch instance.

For example, using the curl command in your Terminal:

# Install Meilisearch
curl -L https://install.meilisearch.com | sh

# Launch Meilisearch
./meilisearch --master-key=masterKey

NB: you can also download Meilisearch from Homebrew or APT or even run it using Docker.

πŸš€ Getting started

Add documents

require 'meilisearch'

client = MeiliSearch::Client.new('http://127.0.0.1:7700', 'masterKey')

# An index is where the documents are stored.
index = client.index('movies')

documents = [
  { id: 1, title: 'Carol', genres: ['Romance', 'Drama'] },
  { id: 2, title: 'Wonder Woman', genres: ['Action', 'Adventure'] },
  { id: 3, title: 'Life of Pi', genres: ['Adventure', 'Drama'] },
  { id: 4, title: 'Mad Max: Fury Road', genres: ['Adventure', 'Science Fiction'] },
  { id: 5, title: 'Moana', genres: ['Fantasy', 'Action']},
  { id: 6, title: 'Philadelphia', genres: ['Drama'] },
]
# If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
index.add_documents(documents) # => { "uid": 0 }

With the uid, you can check the status (enqueued, canceled, processing, succeeded or failed) of your documents addition using the task.

πŸ’‘ To customize the Client, for example, increasing the default timeout, please check out this section of the Wiki.

Basic Search

# Meilisearch is typo-tolerant:
puts index.search('carlo')

Output:

{
  "hits" => [{
    "id" => 1,
    "title" => "Carol"
  }],
  "offset" => 0,
  "limit" => 20,
  "processingTimeMs" => 1,
  "query" => "carlo"
}

Custom search

All the supported options are described in the search parameters section of the documentation.

index.search(
  'wonder',
  attributes_to_highlight: ['*']
)

JSON output:

{
    "hits": [
        {
            "id": 2,
            "title": "Wonder Woman",
            "_formatted": {
                "id": 2,
                "title": "<em>Wonder</em> Woman"
            }
        }
    ],
    "offset": 0,
    "limit": 20,
    "processingTimeMs": 0,
    "query": "wonder"
}

Custom Search With Filters

If you want to enable filtering, you must add your attributes to the filterableAttributes index setting.

index.update_filterable_attributes([
  'id',
  'genres'
])

You only need to perform this operation once.

Note that Meilisearch will rebuild your index whenever you update filterableAttributes. Depending on the size of your dataset, this might take time. You can track the process using the tasks).

Then, you can perform the search:

index.search('wonder', { filter: ['id > 1 AND genres = Action'] })

JSON output:

{
  "hits": [
    {
      "id": 2,
      "title": "Wonder Woman",
      "genres": [
        "Action",
        "Adventure"
      ]
    }
  ],
  "estimatedTotalHits": 1,
  "query": "wonder",
  "limit": 20,
  "offset": 0,
  "processingTimeMs": 0
}

Display ranking details at search

JSON output:

{
  "hits": [
    {
      "id": 15359,
      "title": "Wonder Woman",
      "_rankingScoreDetails": {
        "words": {
          "order": 0,
          "matchingWords": 2,
          "maxMatchingWords": 2,
          "score": 1.0
        },
        "typo": {
          "order": 1,
          "typoCount": 0,
          "maxTypoCount": 2,
          "score": 1.0
        },
        "proximity": {
          "order": 2,
          "score": 1.0
        },
        "attribute": {
          "order": 3,
          "attributeRankingOrderScore": 0.8181818181818182,
          "queryWordDistanceScore": 1.0,
          "score": 0.8181818181818182
        },
        "exactness": {
          "order": 4,
          "matchType": "exactMatch",
          "score": 1.0
        }
      }
    }
  ]
}

This feature is only available with Meilisearch v1.3 and newer (optional).

Custom Search With attributes on at search time

Customize attributes to search on at search time.

you can perform the search :

index.search('wonder', { attributes_to_search_on: ['genres'] })

JSON output:

{
  "hits":[],
  "query":"wonder",
  "processingTimeMs":0,
  "limit":20,
  "offset":0,
  "estimatedTotalHits":0,
  "nbHits":0
}

This feature is only available with Meilisearch v1.3 and newer (optional).

πŸ€– Compatibility with Meilisearch

This package guarantees compatibility with version v1.x of Meilisearch, but some features may not be present. Please check the issues for more info.

πŸ’‘ Learn more

The following sections in our main documentation website may interest you:

πŸ“– Also, check out the Wiki of this repository to know what this SDK provides!

βš™οΈ Contributing

Any new contribution is more than welcome in this project!

If you want to know more about the development workflow or want to contribute, please visit our contributing guidelines for detailed instructions!


Meilisearch provides and maintains many SDKs and Integration tools like this one. We want to provide everyone with an amazing search experience for any kind of project. If you want to contribute, make suggestions, or just know what's going on right now, visit us in the integration-guides repository.

meilisearch-ruby's People

Contributors

adripo avatar alallema avatar andre-m-dev avatar bb avatar bidoubiwa avatar bors[bot] avatar brunoocasali avatar carofg avatar curquiza avatar davidpan avatar dependabot-preview[bot] avatar dependabot[bot] avatar ellnix avatar eskombro avatar flamesrunner avatar gurgeous avatar jmks avatar matboivin avatar mcdostone avatar meili-bors[bot] avatar meili-bot avatar nagaroni avatar qdequele avatar rafaeelaudibert avatar reginaalyssa avatar saintmalik avatar thicolares avatar toshitapandey avatar tpayet avatar zinovik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

meilisearch-ruby's Issues

Test the client option in case of failure.

The MeiliSearch::Client can be initialized with options.

ex:

client = MeiliSearch::Client.new('http://127.0.0.1:8800', 'masterKey', timeout: 20, max_retries: 2)

These options (timeout and max_retries) are not tested in case of failure.

Update settings with nil

If I try to reset a settings via the update_settings method, I can do the following line without any issue:

index.update_settings(distinctAttribute: nil)

But if I try to update a settings via the update_XXX where XXX is the specific settings, I cannot:

index.update_distinct_attribute(nil)
/Users/curquiza/.rvm/gems/ruby-2.6.6/gems/meilisearch-0.14.0/lib/meilisearch/http_request.rb:77:in `validate': 400 Bad Request - Invalid JSON: EOF while parsing a value at line 1 column 0. See https://docs.meilisearch.com/errors#bad_request. (MeiliSearch::ApiError)

(This does not work with the other settings either)

  • Fix in the code
  • Add tests

NDJSON/CSV methods to add and update documents

⚠️ This issue is generated, it means the nameing might be done differently in this package (ex: add_documents_json instead of addDocumentsJson). Keep the already existing way of naming in this package to stay idiomatic with the language and this repository.

πŸ“£ We strongly recommend doing multiple PRs to solve all the points of this issue

MeiliSearch v0.23.0 introduces two changes:

  • new valid formats to push data files, additionally to the JSON format: CSV and NDJSON formats.
  • it enforces the Content-type header for every route requiring a payload (POST and PUT routes)

Here are the expected changes to completely close the issue:

  • Currently, the SDKs always send Content-Type: application/json to every request. Only the POST and PUT requests should send the Content-Type: application/json and not the DELETE and GET ones. #257

  • Add the following methods and πŸ”₯ the associated tests πŸ”₯ to ADD the documents. Depending on the format type (csv or ndjson) the SDK should send Content-Type: application/x-dnjson or Content-Type: text/csv)

    • addDocumentsJson(string docs, string primaryKey) #257
    • addDocumentsCsv(string docs, string primaryKey) #257
    • addDocumentsCsvInBatches(string docs, int batchSize, string primaryKey)
    • addDocumentsNdjson(string docs, string primaryKey) #257
    • addDocumentsNdjsonInBatches(string docs, int batchSize, string primaryKey)
  • Add the following methods and πŸ”₯ the associated tests πŸ”₯ to UPDATE the documents. Depending on the format type (csv or ndjson) the SDK should send Content-Type: application/x-dnjson or Content-Type: text/csv)

    • updateDocumentsJson(string docs, string primaryKey)
    • updateDocumentsCsv(string docs, string primaryKey)
    • updateDocumentsCsvInBatches(string docs, int batchSize, string primaryKey)
    • updateDocumentsNdjson(string docs, string primaryKey)
    • updateDocumentsNdjsonInBatches(string docs, int batchSize, string primaryKey)

docs are the documents sent as String
primaryKey is the primary key of the index
batchSize is the size of the batch. Example: you can send 2000 documents in raw String in docs and ask for a batchSize of 1000, so your documents will be sent to MeiliSearch in two batches.

Example of PRs:


Related to: meilisearch/integration-guides#146

If this issue is partially/completely implemented, feel free to let us know.

Handle new versions of meilisearch

MeiliSearch::CommunicationError: An error occurred while trying to connect to the MeiliSearch instance: Failed to open TCP connection to 127.0.0.1:7700 (Connection refused - connect(2) for "127.0.0.1" port 7700)
/Users/asharifr/.rvm/gems/ruby-2.7.0/gems/meilisearch-0.13.3/lib/meilisearch/http_request.rb:60:in rescue in send_request' /Users/asharifr/.rvm/gems/ruby-2.7.0/gems/meilisearch-0.13.3/lib/meilisearch/http_request.rb:57:in send_request'
/Users/asharifr/.rvm/gems/ruby-2.7.0/gems/meilisearch-0.13.3/lib/meilisearch/http_request.rb:21:in http_get' /Users/asharifr/.rvm/gems/ruby-2.7.0/gems/meilisearch-0.13.3/lib/meilisearch/client.rb:10:in indexes'

Random fail when running tests in CI - timeout and max_retries

Description
The test MeiliSearch allows to set a custom timeout and max_retries happens to fail randomly, though quite rarely.

Current behavior

  • This fail never happens in local on mac os x.
  • Seen multiple time with Linux ubuntu VM cf: Environment
  • One time from now on CI

Logs

Expand to see logs
MeiliSearch
  has a version number
  raises an exception when it is impossible to connect
  allows to set a custom timeout and max_retries (FAILED - 1)

Failures:

  1) MeiliSearch allows to set a custom timeout and max_retries
     Failure/Error:
       expect do
         client.indexes
       end.to raise_error(Timeout::Error)

       expected Timeout::Error but nothing was raised
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-support-3.10.2/lib/rspec/support.rb:102:in `block in <module:Support>'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-support-3.10.2/lib/rspec/support.rb:111:in `notify_failure'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.10.1/lib/rspec/expectations/fail_with.rb:35:in `fail_with'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.10.1/lib/rspec/expectations/handler.rb:40:in `handle_failure'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.10.1/lib/rspec/expectations/handler.rb:56:in `block in handle_matcher'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.10.1/lib/rspec/expectations/handler.rb:27:in `with_matcher'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.10.1/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.10.1/lib/rspec/expectations/expectation_target.rb:65:in `to'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.10.1/lib/rspec/expectations/expectation_target.rb:101:in `to'
     # ./spec/meilisearch_spec.rb:17:in `block (2 levels) in <top (required)>'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:262:in `instance_exec'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:262:in `block in run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:508:in `block in with_around_and_singleton_context_hooks'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:465:in `block in with_around_example_hooks'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:486:in `block in run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:624:in `run_around_example_hooks_for'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:486:in `run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:465:in `with_around_example_hooks'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:508:in `with_around_and_singleton_context_hooks'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:259:in `run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:644:in `block in run_examples'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:640:in `map'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:640:in `run_examples'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:606:in `run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `block (3 levels) in run_specs'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `map'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `block (2 levels) in run_specs'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/configuration.rb:2067:in `with_suite_hooks'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:116:in `block in run_specs'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/reporter.rb:74:in `report'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:115:in `run_specs'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:89:in `run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:71:in `run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:45:in `invoke'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/rspec-core-3.10.1/exe/rspec:4:in `<top (required)>'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/bin/rspec:23:in `load'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/bin/rspec:23:in `<top (required)>'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/cli/exec.rb:74:in `load'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/cli/exec.rb:74:in `kernel_load'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/cli/exec.rb:28:in `run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/cli.rb:463:in `exec'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/cli.rb:27:in `dispatch'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/cli.rb:18:in `start'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/bundler-1.17.2/exe/bundle:30:in `block in <top (required)>'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/2.6.0/bundler/friendly_errors.rb:124:in `with_friendly_errors'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/lib/ruby/gems/2.6.0/gems/bundler-1.17.2/exe/bundle:22:in `<top (required)>'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/bin/bundle:23:in `load'
     # /opt/hostedtoolcache/Ruby/2.6.7/x64/bin/bundle:23:in `<main>'

Finished in 2.61 seconds (files took 0.34938 seconds to load)
162 examples, 1 failure

Failed examples:

rspec ./spec/meilisearch_spec.rb:15 # MeiliSearch allows to set a custom timeout and max_retries

Environment

  • OS: ubuntu 20.04
  • Meilisearch: v0.20.0
  • Ruby: 2.6.7

Suggestion

  • This test fail every time if we use timeout: 1, because the client doesn't have time to timeout before receiving the server response:
  it 'allows to set a custom timeout and max_retries' do
    client = MeiliSearch::Client.new($URL, $MASTER_KEY, timeout: 1, max_retries: 2)
    expect do
      client.indexes
    end.to raise_error(Timeout::Error)
  end

It happens when timeout: 0 for the same reason.

Upgrade rubocop.yml according to the warning

Currently, when we run

$ bundle exec rubocop lib/ spec/
The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file:
 - Layout/EmptyLinesAroundAttributeAccessor (0.83)
 - Layout/SpaceAroundMethodCallOperator (0.82)
 - Lint/DeprecatedOpenSSLConstant (0.84)
 - Lint/MixedRegexpCaptureTypes (0.85)
 - Lint/RaiseException (0.81)
 - Lint/StructNewOverride (0.81)
 - Style/ExponentialNotation (0.82)
 - Style/HashEachMethods (0.80)
 - Style/HashTransformKeys (0.80)
 - Style/HashTransformValues (0.80)
 - Style/RedundantFetchBlock (0.86)
 - Style/RedundantRegexpCharacterClass (0.85)
 - Style/RedundantRegexpEscape (0.85)
 - Style/SlicingWithRange (0.83)
For more information: https://docs.rubocop.org/rubocop/versioning.html

We should fix the warning with the more convenient configuration for our code base.

Add `updatedAt` and `createdAt` to `Index`

When manipulating indexes (get/create/update), the MeiliSearch server returns the following information related to the index:

  • uid: the uid of the index
  • primaryKey: the primary key of the index
  • updateAt: when the index has been updated
  • createdAt: when the index has been created

This SDK, when manipulating indexes (get/create/update) returns an instance of Index which already contains the primaryKey and uid members.

It means we can currently get the primaryKey and the uid, but not updatedAt and createdAt.

TODO:

  • Add updatedAt and createdAt member in the Index class/struct (depending on the language).
  • Update the variable in the code where primaryKey is already updated. Ex: when getting the index with getIndex()
  • Add tests

⚠️ This issue is generated, it means primaryKey, updatedAt, and createdAt might be named differently in this package (ex: primary_key instead). Keep the already existing way of naming in this package to stay idiomatic with the language and the repository.
Also, if you are a maintainer, feel free to add any clarification and instruction about this issue related to the specific languages of the repo.

Related to meilisearch/integration-guides#121

Sorry if this is already partially/completely implemented, feel free to let me know about the state of this issue in the repo.

Accept integer as a query parameter

When I try to search with an integer instead of a string as the query parameter, I'm getting an error like the following:
400 Bad Request - Invalid JSON: invalid type: integer 42, expected a string

I'd like to run: index.search(42) and get results instead of an error.

Algolia accepts an integer and transforms it into a string before sending the request. Check the source code here

Improve adding lots of documents and error handling when reaching maximum payload size

I started off with indexing just a few fields of my test data running index.add_documents(documents) was just fine. After adding a few more fields, it broke like this:

> index.add_documents(documents)
Errno::EPIPE: Broken pipe
from <internal:prelude>:131:in `__write_nonblock'

I could only guess that I reached the maximum payload size and indeed: documents.to_json.length/1.megabyte returned 12 while the default limit is 10.

I'd prefer if the client would handle the failed request more gracefully with a helpful error message.

It might even detect the problem before sending the request by checking the expected payload size against the servers configured value (not sure if this is exposed via API yet).

I was able to successfully add all documents in slices:

documents.each_slice(100) {|d1| index.add_documents(d1) }

Even though I understand that it's not a good idea to serialize a complete dataset, especially in production, I wonder if adding convenience features automatic sending in chunks to the ruby client would be a good idea. What do you think?

Create and fill sample file to display Ruby examples in MeiliSearch Documentation

Code Samples for MeiliSearch documentation

Introduction

As MeiliSearch grows so does its SDK's. More and more SDK's rises from the ground and they all deserve to be as well documented as the core engine itself.

The most common way for a user to understand MeiliSearch is to go to its official documentation. As of yesterday all examples in the documentation were made with cURL. Unfortunately, most of our users do not communicate with MeiliSearch directly with cURL. Which forces them to search for the specific references somewhere else (in the readme's, in the sdk's code itself,..). This makes for unnecessary friction.

Goal

We want our documentation to include all SDK's

As a first step we want all examples to be made using the most possible SDK's. As did Stripe and Algolia.

sdk_sample

examples with curl, javascript and soon enough this SDK too!

To achieve this it is expected from this SDK to create a sample file containing all the code samples needed by the documentation.

These are the steps to follow:

  • Create your sample file
  • Fill your sample file
  • Add your samples to the documentation

Create your sample file

The sample file is a yaml file added at the root of each MeiliSearch SDK.
Sample files are created based on the sample-template.yaml file.

sample-template file:

get_one_index_1: |-
list_all_indexes_1: |-
create_an_index_1: |-
...

This template is accessible publicly here or in the public directory : .vuepress/public/sample-template.yaml of the documentation.

The name of the file should be .code-samples.meilisearch.yaml

Fill your sample file

After creating the sample file with the content of the sample template you should have a file containing all the sampleId's.

get_one_index_1: |-
list_all_indexes_1: |-
create_an_index_1: |-
...

By the name of the different sampleId you should know where that code sample will be added to the documentation.

For example, create_an_index_1 is the first example in the API References of the index creation.

Using the already existing cURL example in the documentation you should see what is expected from that sample. It is very important that you look at the already existing samples in the documentation as it gives you the parameters to use in your sample to match with the rest of the documentation.

Good sample based on documentation:

create_an_index_1: |-
  client.createIndex({ uid: 'movies' })

Bad sample that does not match with the response.

create_an_index_1: |-
  client.createIndex({ uid: 'otherName' })

Each sample is expected to be written in the respective SDK language.

Javascript example:

get_one_index_1: |-
  client.getIndex('movies').show()
list_all_indexes_1: |-
  client.listIndexes()
create_an_index_1: |-
  client.createIndex({ uid: 'movies' })
  ...

The complete cURL sample file is available at the root of the documentation repository.
Every other SDK sample file should be available at the root of their respective repository.

Formatting Exception

There is one exception to the formatting rule.
When the sampleId finishes with _md it means it is expected to be written in markdown format.

JavaScript sample id with _md extension:
yaml-js-example

Add your samples to the documentation

Once your sample file is filled with the code samples, you will need to create a pull request on the documentation repository.

Open the following file in your IDE:
.vuepress/code-samples/sdks.json

And add your sample file to the list:

[
  ...
  {
    "language": "sdk-language",
    "label": "sdk-label",
    "url": "url to yaml file"
  }
]

The language key expect a supported language for the code highlight.

The label key is the name of the tab. While label and language could have been the same, it created some conflict (i.e: bash and cURL).

The url is the raw link to access your sample file. It should look like this:
https://raw.githubusercontent.com/[PROJECT]/[REPO]/.code-samples.meilisearch.yaml

Update .code-samples.meilisearch.yaml

Related to meilisearch/integration-guides#155

Following the documentation issue (meilisearch/documentation#1290) and PR (meilisearch/documentation#1214) an additional code-sample must be added in the .code-samples.meilisearch.yaml file at the root of the repository.

Information:

Using the following information the code-sample must be created in the repository language.

  • code-sample id: settings_guide_sortable_1
  • index: books
  • route: /settings
  • method: POST
  • content-type: application/json
  • data body:
    {
      "sortableAttributes": [
        "price",
        "author"
      ]
    }

Code Example

In cURL the samples is defined the following way:

curl \
  -X POST 'http://localhost:7700/indexes/books/settings' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "sortableAttributes": [
      "price",
      "author"
    ]
  }'

Make the tests independent

Currently, some tests depend on the previous ones, like in this file: https://github.com/meilisearch/meilisearch-ruby/blob/master/spec/meilisearch/client/indexes_spec.rb.

We should re-write the test suite to make the tests independent from the others. This would make our test suite more readable, trustable, and maintainable.

Independent tests mean that each test method begins with an empty MeiliSearch instance. We should automate the index creation at the beginning of each test.

undefined method `compact' for Hash

I try to test meilisearch gem with ruby 2.3.3. But I can't create a connection to MeiliSearch. It shows an error.

irb(main):002:0> client = MeiliSearch::Client.new('http://127.0.0.1')
NoMethodError: undefined method `compact' for {"Content-Type"=>"application/json", "X-Meili-API-Key"=>nil}:Hash
        from /Users/xluffy/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/meilisearch-0.15.0/lib/meilisearch/http_request.rb:17:in `initialize'
        from (irb):2:in `new'
        from (irb):2
        from /Users/xluffy/.rbenv/versions/2.3.3/bin/irb:11:in `<main>'

compact is a method of Hash in Ruby 2.4.0. I checked meilisearch documents but don't see any warning about Ruby version is compatible.

This is not a big issue. But I think we could make a better experience for users. We can try two solutions:

  • Update a document with compatible Ruby version + add spec.required_ruby_version = '>= 2.4' in gemspec file.
  • Support version Ruby < 2.4

Update .code-samples.meilisearch.yaml

Following meilisearch/documentation#1214, we would like to apply some changes in the .code-samples.meilisearch.yaml file at the root of the repository

  • Regarding get_distinct_attribute_1, update_distinct_attribute_1 and reset_distinct_attribute_1: if present, the index name should be shoes
  • Regarding update_distinct_attribute_1: the distinct attribute passed should be skuid and not movie_id

Cannot load such file `meilisearch/utils`

I now get

Traceback (most recent call last):
	3: from test.rb:4:in `<main>'
	2: from test.rb:4:in `require'
	1: from /Users/curquiza/.rvm/gems/ruby-2.6.6/gems/meilisearch-0.17.1/lib/meilisearch.rb:4:in `<top (required)>'
/Users/curquiza/.rvm/gems/ruby-2.6.6/gems/meilisearch-0.17.1/lib/meilisearch.rb:4:in `require': cannot load such file -- meilisearch/utils (LoadError)

when trying to use v0.17.1 πŸ˜…

Pass parameters using snake case

Currently, when sending payload to MeiliSearch via this package, we use snake case:

index.search(
  'hob',
  attributesToHighlight: ['*']
)

This is because the HashMap is directly sent to MeiliSearch without any transformation, and MeiliSearch only accepts camelCase.

However, using camelCase is not idiomatic in ruby. We would like make this package accepts snake case as well

index.search(
  'hob',
  attributes_to_highlight: ['*']
)

An external contributor already did it on meilisearch-rails, see https://github.com/meilisearch/meilisearch-rails/pull/49/files

We are open to contributions, feel free to ask any question :)

Add method to get the raw index information

⚠️ This issue is generated, it means the examples and the namings do not necessarily correspond to the language of this repository.
Also, if you are a maintainer, feel free to add any clarification and instruction about this issue.

Sorry if this is already partially/completely implemented, feel free to let me know about the state of this issue in the repo.

Related to meilisearch/integration-guides#120


This SDK provides a method to get an index (getIndex) and this method returns an instance of Index. Some users want to get the raw version of the index, I mean the exact JSON response returned by the MeiliSearch server, not an instance.

Some SDKs already provide a way to get this raw index information but this is not convenient, example in PHP:

$client->index('movies')->fetchRawInfo();

We need to add the getRawIndex method, accessible from the Client instance, to make it more convient.

Prototype:

getRawIndex(string indexUID) -> object/struct/dict of the MeiliSearch response

Ex in PHP:

$client->getRawIndex('movies');

TODO:

  • Add getRawIndex() method to the Client instance without duplicating the code (if fetchRawInfo() already exists for example)
  • Add tests

Add a docker-compose to ease local development

Description

Ease collaboration and local development by utilizing virtualization with Docker. So we don't need to install basic dependencies and can keep them up-to-date by design.

Tasks

  • Create a docker-composer file containing (1) a ruby container and (2) a meilisearch container talking to each other;
  • Expose basic settings, e.g. meilisearch service's host and port, via ENV variables;
  • Update the CONTRIBUTING.md page with related tips.

Other

I believe there're other improvements related to this topic, but maybe that's already a good starting point :)

MeiliSearch::Index times out

MeiliSearch::Index times out when indexing a lot of data. The default timeout is 1.

The following page states that the timeout can be increased:
https://github.com/meilisearch/meilisearch-ruby/wiki/Client-Options

However, the MeiliSearch::Client does not pass the options to MeiliSearch::Index, so the default timeout and max_retries is always used:

def index_object(uid, primary_key = nil)
Index.new(uid, @base_url, @api_key, primary_key)
end

def initialize(index_uid, url, api_key = nil, primary_key = nil)
@uid = index_uid
@primary_key = primary_key
super(url, api_key)
end

Simplify the code

Make the code and file organization less complex because we don't have a lot of code yet. No need to complexify the work and to have as many files as we have right now. We will organize better when needed.

This change is useful for new contributors.

Configurable timeout and ability to enable retry strategy

I'd like to have ability to configure timeout and optionally enable number of retries in case of timeout.

I'm trying to index large amount of json documents (overall size 8.5 GB in single gziped file). I'm adding these documents bu relatively small chunks (from 1000 to 5000 docs in one chunk) and quite often requests being timeout even unable to post data to the meilisearch instance. I think 1 second timeout is too short.

Also, HTTParty has ability to set number of retries and I'd like to be able to enable this feature in client when required.

Method to get all the indexes should return a list of instance

Currently, the get_all_indexes method returns a raw list of object, but not a list of Index instance. This is the only index-related method that does not return an Index instance.

An instance is more convenient to manipulate than a raw object. See this example.

TODO

  • Change the return of the current get_all_indexes: make it return a list of Index instances
  • Provide get_all_raw_indexes: a method that returns the list of object of indexes, so the response of the MeiliSearch server.
  • Add tests

⚠️ No code duplication: use get_all_raw_indexes in get_all_indexes.

Related to meilisearch/integration-guides#122

⚠️ Also, this issue is generated, and get_all_indexes might be named differently in this package. Keep the already existing way of naming in this package to stay idomatic with the language and the repository.

Sorry if this is already partially/completely implemented, feel free to let me know about the state of this issue.

Add good practices to test suite

Hi!

Looking to the code, I saw that we have some improvements that could be made by using some techniques or just good practices when testing ruby code.

TODO:

  • Remove all global variables from test code #238
  • Remove @client variables and friends, replace by let's/shared contexts
  • #122 #230
  • Use context/describe to separate contexts of tests between examples #255

Handle 5xx errors when running behind some ELB or Nginx

When MeiliSearch is running behind any reverse proxy and do not respond to the request in time, gateway may return plain HTTP error page. Client tries to parse such response in order to determine if there any errors and end up raising JSON::ParseError.

In my opinion such kind of errors should be handled based on response's http code and handled accordingly.

Error when calling "client.get_or_create_index" & index already exists

In Rails project, I call that method "client.get_or_create_index ('posts')" as an after_create callback in my model. So each time a new instance is saved in the DB, it is also indexed by meilisearch.
When I create the first instance in console, I get no errors (index doesn't exist yet). But, when I try to create a second instance, I get the following error :

MeiliSearch::ApiError (MeiliSearch::ApiError - code: - type: - message: Impossible to create index; index already exists - link: )

Change `books` to `movies` in README.md

To keep the getting started simple to try, but to also make documentation examples compatible with the getting started, we are replacing book examples with movies examples.

The Movie dataset is used throughout the documentation. The only place where book is used is in the tests (which can stay as it is) and in our getting started.

Changes

  • Index name should be changed in README.md
  const index = client.index('movies')

Provided dataset should be changed with the following:

 const documents = [
      { id: 1, title: 'Carol', genres: ['Romance', 'Drama'] },
      { id: 2, title: 'Wonder Woman', genres: ['Action', 'Adventure'] },
      { id: 3, title: 'Life of Pi', genres: ['Adventure', 'Drama'] },
      { id: 4, title: 'Mad Max: Fury Road', genres: ['Adventure', 'Science Fiction'] },
      { id: 5, title: 'Moana', genres: ['Fantasy', 'Action']},
      { id: 6, title: 'Philadelphia', genres: ['Drama'] },
  ]
  • comment should be changed
// If the index 'movies' does not exist, MeiliSearch creates it when you first add the documents.
  • All the other examples in the README should be updated accordingly

Add a method to delete the index only if it already exists

Trying to delete an index that does not exist on the MeiliSearch server will throw an error. To delete it without any error no matter what if it exists or not, we need a new method.

  • Add a method delete_index_if_exists: it deletes the index but does not throw any error if the index does not exist.
  • Add tests

Example: https://github.com/meilisearch/meilisearch-python/pull/268/files

⚠️ This issue is generated, and delete_index_if_exists might be named differently in this package. Keep the already existing way of naming in this package to stay idomatic with the language and the repository.

Related to meilisearch/integration-guides#107

Sorry if this is already partially/completely implemented, feel free to let me know about the state of this issue.

Improve search tests

Add more tests for the search methods.

  • Test, at least, each search parameter individually.
  • add, if possible, more "multiple search parameters" example.

Could be done in multiple PR of course πŸ™‚

Change master branch to main

Let's be allies and make this change that means a lot.

Here is a blog post that explain a little more why it's important, and how to easily do it. It will be a bit more complicated with automation, but we still should do it!

Search parametters don't accept lists of strings (and should)

Search parameters like attributesToRetrieve can't handle a list of strings. You should be able to pass a list of fields, not just a single string or '*'.

Example

response = @index.search('the', attributesToRetrieve: ['title', 'release_date'])

Failing test

Screenshot 2020-06-02 at 19 35 41

Add a search example with `filter` in README

⚠️ This issue is generated, please adapt the example to the repository language.

Related to: meilisearch/integration-guides#136

In the README, we want to add the Custom Search With Filters sub section in the Getting Started section to make the users are aware of filtering.

This should

  • be placed right after the Custom Search sub section
  • contain the following content:

---------- beginning of the content

If you want to enable filtering, you must add your attributes to the filterableAttributes index setting.

--- Add an example corresponding to the current repository. See this example in JS:

await index.updateAttributesForFaceting([
    'id',
    'genres'
  ])

--- end of example

You only need to perform this operation once.

Note that MeiliSearch will rebuild your index whenever you update filterableAttributes. Depending on the size of your dataset, this might take time. You can track the process using the update status.

Then, you can perform the search:

--- Add an example corresponding to the current repository. See this example in JS:

await index.search(
  'wonder',
  {
    filter: ['id > 1 AND genres = Action']
  }
)

--- end of example

{
  "hits": [
    {
      "id": 2,
      "title": "Wonder Woman",
      "genres": ["Action","Adventure"]
    }
  ],
  "offset": 0,
  "limit": 20,
  "nbHits": 1,
  "processingTimeMs": 0,
  "query": "wonder"
}

------------- end of the content

πŸ“£ Example of PR: https://github.com/meilisearch/meilisearch-js/pull/1059/files

⚠️ Snake case issue in v0.17.0

v0.17.0 of this package is broken -> it transforms the attributes of the user documents

example, if I try to push this document

[
  { "id": 2,    "my_title": "Pride and Prejudice" },
]

it will push the following document

[
  { "id": 2,    "myTitle": "Pride and Prejudice" },
]

which is not what we expect, the document of the user should stay unchanged

@brunoocasali, since you introduced the snake case compatibility (we expected for settings only, not the documents) in #237, do you know how to fix this?

I tried to revert the PR, but GitHub does not want to apply a revert here.

We also should add a test importing a document with snake case attributes and check this is well imported to MeiliSearch.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.