{"id":13809210,"url":"https://github.com/WTTJ/algoliax","last_synced_at":"2025-05-14T05:33:28.473Z","repository":{"id":42686839,"uuid":"198698866","full_name":"WTTJ/algoliax","owner":"WTTJ","description":"Algolia integration to elixir application","archived":false,"fork":false,"pushed_at":"2025-05-12T04:51:57.000Z","size":389,"stargazers_count":62,"open_issues_count":6,"forks_count":17,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-05-13T01:44:38.255Z","etag":null,"topics":["algolia","ecto","elixir","elixir-application","elixir-lang","phoenix"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WTTJ.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-24T19:36:51.000Z","updated_at":"2025-05-12T02:20:40.000Z","dependencies_parsed_at":"2024-05-01T17:21:13.201Z","dependency_job_id":"19743beb-2515-40f5-918d-f2240f0d6de9","html_url":"https://github.com/WTTJ/algoliax","commit_stats":{"total_commits":164,"total_committers":14,"mean_commits":"11.714285714285714","dds":0.4390243902439024,"last_synced_commit":"8dff34bda3cce40a2472ca553c3250a7d54448e3"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WTTJ%2Falgoliax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WTTJ%2Falgoliax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WTTJ%2Falgoliax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WTTJ%2Falgoliax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WTTJ","download_url":"https://codeload.github.com/WTTJ/algoliax/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254077014,"owners_count":22010641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algolia","ecto","elixir","elixir-application","elixir-lang","phoenix"],"created_at":"2024-08-04T01:02:08.990Z","updated_at":"2025-05-14T05:33:28.464Z","avatar_url":"https://github.com/WTTJ.png","language":"Elixir","readme":"# Algoliax\n\n[![CircleCI](https://circleci.com/gh/WTTJ/algoliax/tree/main.svg?style=svg)](https://circleci.com/gh/WTTJ/algoliax/tree/main)\n[![Module Version](https://img.shields.io/hexpm/v/algoliax.svg)](https://hex.pm/packages/algoliax)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/algoliax/)\n[![Total Download](https://img.shields.io/hexpm/dt/algoliax.svg)](https://hex.pm/packages/algoliax)\n[![License](https://img.shields.io/hexpm/l/algoliax.svg)](https://github.com/WTTJ/algoliax/blob/master/LICENSE.md)\n[![Last Updated](https://img.shields.io/github/last-commit/WTTJ/algoliax.svg)](https://github.com/WTTJ/algoliax/commits/master)\n\nThis package let you easily integrate Algolia to your Elixir application. It can be used with built in Elixir struct or with [Ecto](https://github.com/elixir-ecto/ecto) schemas.\n\n## Installation\n\nThe package can be installed by adding `:algoliax` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:algoliax, \"~\u003e 0.10.0\"}\n  ]\nend\n```\n\nIf using with Ecto schemas, Algoliax requires `:ecto`.\n\n## Configuration\n\nAlgoliax needs only `:api_key` and `:application_id` config. These configs can either be on config files or using environment variables `ALGOLIA_API_KEY` and `ALGOLIA_APPLICATION_ID`.\n\n```elixir\nconfig :algoliax,\n  api_key: \"\u003cAPI_KEY\u003e\",\n  application_id: \"\u003cAPPLICATION_ID\u003e\",\n  batch_size: 500,\n  recv_timeout: 5000\n```\n\n## Usage\n\n```elixir\ndefmodule People do\n  use Algoliax.Indexer,\n    index_name: :algoliax_people,\n    object_id: :reference,\n    algolia: [\n      attributes_for_faceting: [\"age\"],\n      searchable_attributes: [\"full_name\"],\n      custom_ranking: [\"desc(updated_at)\"]\n    ]\n\n  defstruct reference: nil, last_name: nil, first_name: nil, age: nil\nend\n```\n\nOverridable functions:\n\n- `to_be_indexed/1` which take the model struct in parameter: allows to choose to index or not the current model\n\n```elixir\ndefmodule People do\n  ...\n\n  @impl Algoliax\n  def to_be_indexed?(person) do\n    person.age \u003e 20\n  end\nend\n\n# This object will be indexed\npeople1 = %People{reference: 10, last_name: \"Doe\", first_name: \"John\", age: 13}\n\n# This object will not be indexed\npeople2 = %People{reference: 87, last_name: \"Fred\", first_name: \"Al\", age: 70}\n```\n\n- `build_object/1` which take the model struct/map in parameter and should return a Map: allow to add attributes to the indexed object. By default the object contains only an `ObjectID`.\n\n```elixir\ndefmodule People do\n  ...\n\n  @impl Algoliax\n  def build_object(person) do\n    %{\n      age: person.age,\n      now: Date.utc_today()\n    }\n  end\nend\n```\n\n- `build_object/2` does the same but provides the current index name as a second parameter. Can be useful when indexing the same model on multiple indexes (ie. for translations).\n\n```elixir\ndefmodule Article do\n  ...\n\n  @impl Algoliax\n  def build_object(author, \"article_index_\" \u003c\u003e locale) do\n    %{\n      author: article.author,\n      content: article.content[locale]\n    }\n  end\nend\n```\n\n#### Index name at runtime\n\nIt's possible to define an index name at runtime, useful if `index_name` depends on environment or comes from an environment variable.\n\nTo do this just define a function with an arity of 0 that will be used as `index_name`\n\n```elixir\ndefmodule People do\n  use Algoliax.Indexer,\n    index_name: :algoliax_people,\n    object_id: :reference,\n    algolia: [...]\n\n  def algoliax_people do\n    System.get_env(\"PEOPLE_INDEX_NAME\")\n  end\nend\n```\n\n#### Multiple indexes\n\nIt's possible to define multiple indexes for a same model.\n\nTo achieve this, just specify an array of index names, or simply return an array in your `index_name/0` runtime function\n\n```elixir\ndefmodule Article do\n  use Algoliax.Indexer,\n    index_name: [:algoliax_article_fr, :algoliax_article_en],\n    object_id: :reference,\n    algolia: [...]\nend\n```\n\n#### Index functions\n\n```elixir\n# Get people index settings\nPeople.get_settings()\n\n# Delete index\nPeople.delete_index()\n\n# Configure index\nPeople.configure_index()\n```\n\n#### Object functions\n\n```elixir\n# Save object\nPeople.save_object(people1)\n\n# Save multiple objects\nPeople.save_objects([people1, people2])\n\n# Save multiple objects, and ensure object that they can't be indexed anymore are deleted from the index\nPeople.save_objects([people1, people2], force_delete: true)\n\n# Get object\nPeople.get_object(people1)\n\n# Delete object\nPeople.delete_object(people1)\n```\n\n#### Search functions\n\n```elixir\n# search in index\nPeople.search(\"john\")\n\n# search facet\nPeople.search_facet(\"age\")\n```\n\n#### Ecto specific\n\nFirst you will need to add the Repo to the algoliax config:\n\n```elixir\nuse Algoliax.Indexer,\n  index_name: :algoliax_people,\n  object_id: :reference\n  repo: MyApp.Repo,\n  algolia: [...]\n```\n\nIf using Agoliax with an Ecto schema it is possible to use `reindex` functions. Reindex will go through all entries in the corresponding table (or part if query is provided). Algoliax will save_objects by batch of 500.\n`batch_size` can be configured\n\n```elixir\nconfig :algoliax,\n  batch_size: 250\n```\n\n\u003e **NOTE:** Algoliax use by default the `id` column to order and go through the table. (cf [Custom order column](#custom-order-column))\n\n```elixir\nimport Ecto.Query\n\n# Reindex all\nPeople.reindex()\n\n# Reindex all people with age greater than 20\nquery = from(p in People, where: p.age \u003e 20)\nPeople.reindex(query)\n\n# Reindex can also `force_delete`\nquery = from(p in People, where: p.age \u003e 20)\nPeople.reindex(query, force_delete: true)\nPeople.reindex(force_delete: true)\n\n# Reindex atomically (create a temporary index and move it to initial index)\nPeople.reindex_atomic()\n```\n\n##### Custom cursor column\n\nIf you don't have an `id` column, you can change it by setting the `cursor_field` option either in the global settings or in schema specific settings.\n\nMake sure this column ensure a consistent order even when new records are created.\n\n- Using the global config:\n\n```elixir\nconfig :algoliax,\n  batch_size: 250,\n  cursor_field: :reference\n```\n\n- Indexer specific:\n\n```elixir\ndefmodule People do\n  use Algoliax.Indexer,\n    index_name: :algoliax_people,\n    object_id: :reference,\n    repo: MyApp.Repo,\n    cursor_field: :inserted_at,\n    algolia: [...]\nend\n```\n\n#### Replicas configuration\n\nReplicas can be configured using `:replicas` options. This option accepts the following `:index_name`, `:algolia` and `:inherit`.\nUse `inherit: true` on the replica if you want it to inherit from the primary settings, if custom settings in `:algolia` they will be merged.\n\n```elixir\nuse Algoliax.Indexer,\n  index_name: :algoliax_people,\n  object_id: :reference,\n  repo: MyApp.Repo,\n  algolia: [\n    attributes_for_faceting: [\"age\"],\n    searchable_attributes: [\"full_name\"],\n  ],\n  replicas: [\n    [index_name: :algoliax_by_age_asc, inherit: true, algolia: [ranking: [\"asc(age)\"]]],\n    [index_name: :algoliax_by_age_desc, inherit: false, algolia: [ranking: [\"desc(age)\"]]]\n  ]\n```\n\nIf the main index holds multiple indexes (e.g for an index per language usecase), replicas need to hold the same amount of names.\nThe order is important to be associated to the correct main index.\n\n```elixir\nuse Algoliax.Indexer,\n  index_name: [:algoliax_article_en, :algoliax_article_fr],\n  object_id: :reference,\n  repo: MyApp.Repo,\n  algolia: [\n    attributes_for_faceting: [\"published_at\"],\n    searchable_attributes: [\"content\"],\n  ],\n  replicas: [\n    [index_name: [:algoliax_article_by_publication_asc_en, :algoliax_article_by_publication_asc_fr], inherit: true, algolia: [ranking: [\"asc(published_at)\"]]],\n    [index_name: [:algoliax_article_by_publication_desc_en, :algoliax_article_by_publication_desc_fr], inherit: false, algolia: [ranking: [\"desc(published_at)\"]]]\n  ]\n```\n\n## Configure index name at runtime\n\nTo support code for multiple environments, you can also define the index name at runtime. To achieve this, create a function within your indexer module and reference it using its atom in the Indexer configuration.\n\n```elixir\ndefmodule People do\n  use Algoliax.Indexer,\n    index_name: :runtime_index_name,\n    #....\n\n  def runtime_index_name do\n    System.get_env(\"INDEX_NAME\")\n  end\nend\n```\n\n## Copyright and License\n\nCopyright (c) 2020 CORUSCANT (welcome to the jungle) - \u003chttps://www.welcometothejungle.com\u003e\n\nThis library is licensed under the [BSD-2-Clause](./LICENSE.md).\n","funding_links":[],"categories":["Search"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWTTJ%2Falgoliax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FWTTJ%2Falgoliax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWTTJ%2Falgoliax/lists"}