{"id":13416483,"url":"https://github.com/geoffreylitt/simple_recommender","last_synced_at":"2025-04-12T05:36:46.075Z","repository":{"id":16590401,"uuid":"79765599","full_name":"geoffreylitt/simple_recommender","owner":"geoffreylitt","description":"A simple recommendation engine for Rails/Postgres","archived":false,"fork":false,"pushed_at":"2023-01-20T06:18:53.000Z","size":58,"stargazers_count":126,"open_issues_count":13,"forks_count":13,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T12:46:52.999Z","etag":null,"topics":["postgres","rails","recommendation-engine"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geoffreylitt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-23T03:17:25.000Z","updated_at":"2025-03-31T00:53:09.000Z","dependencies_parsed_at":"2023-02-12T00:16:09.940Z","dependency_job_id":null,"html_url":"https://github.com/geoffreylitt/simple_recommender","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffreylitt%2Fsimple_recommender","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffreylitt%2Fsimple_recommender/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffreylitt%2Fsimple_recommender/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffreylitt%2Fsimple_recommender/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geoffreylitt","download_url":"https://codeload.github.com/geoffreylitt/simple_recommender/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248524853,"owners_count":21118615,"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":["postgres","rails","recommendation-engine"],"created_at":"2024-07-30T21:00:59.443Z","updated_at":"2025-04-12T05:36:46.038Z","avatar_url":"https://github.com/geoffreylitt.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# simple_recommender\n\n🔍 A quick and easy way to get \"Users who liked X also liked Y\" recommendations\nfor related items in your Rails/Postgres application.\n\n```ruby\nbook = Book.find_by(name: \"Harry Potter\")\n\n# Find the books most similar to Harry Potter, based on users' likes\nbook.similar_items\n# =\u003e [#\u003cBook id: 1840, name: \"Twilight\"\u003e,\n      #\u003cBook id: 1231, name: \"Redwall\"\u003e,\n      #\u003cBook id: 1455, name: \"Lord of the Rings\"\u003e...]\n```\n\n**Why should I used this gem?**\n\nUnlike similar gems like [predictor](https://github.com/Pathgather/predictor) and [recommendable](https://github.com/davidcelis/recommendable) that require you to track relationships between entities in Redis, simple_recommender uses the associations you already have in your Postgres database.\n\nThis means you don't have to maintain a separate copy of your data, and also don't incur the operational complexity of needing to use Redis. Hooray for simplicity!\n\nFor more background on the idea behind the gem, see [this blog post](https://www.geoffreylitt.com/2017/03/19/building-a-rails-recommendation-engine.html).\n\n**But is it fast enough?**\n\nsimple_recommender uses fast integer array operations built into Postgres,\nso it's fast enough to return realtime recommendations for many applications.\n\nAs a rough guideline based on benchmarking with a Heroku Standard 0 database:\nif you have under 100,000 records in your join table (e.g., less than 100,000\nLikes in the above example), then simple_recommender can return queries within\na couple hundred milliseconds.\n\nIf you're not sure if this is fast enough for your use case, I would recommend\ntrying it out on your data; it's just a couple lines of code to get started.\n\nIf you know that you have way more data than that, I would recommend looking into\none of the Redis-based gems that allow for offline precomputation. I'm also\nconsidering adding offline precomputation to this gem to allow for higher scale.\n\n## Getting started\n\n### Prerequisites\n\nThis gem requires:\n\n* Rails 4+\n* PostgreSQL ([setup guide](https://www.digitalocean.com/community/tutorials/how-to-setup-ruby-on-rails-with-postgres))\n\n### Installation\n\n##### Install the gem\n\n* Add the gem to your Gemfile: `gem 'simple_recommender'`\n\n* Run `bundle install`\n\n##### Enable `intarray`\n\nNext you'll need to enable the `intarray` extension in your Postgres database, which is used to compute recommendations.\n\n* Run `rails g migration EnableIntArrayExtension`\n\n* Replace the contents of the newly created migration file with the code below\n\n```\nclass EnableIntArrayExtension \u003c ActiveRecord::Migration\n  def change\n    enable_extension \"intarray\"\n  end\nend\n```\n\n* Run `rake db:migrate`\n\nNow you should have everything you need to get started!\n\n## Usage\n\nYou can add `include SimpleRecommender::Recommendable` to any ActiveRecord model,\nand then define an association to use for similarity matching.\n\nFor example, let's say you have Books in your app. Books are associated with Users through Likes. We want to say that two books are similar if they are liked by many of the same users.\n\nIt's as easy as adding two lines to your model:\n\n```ruby\nclass Book \u003c ActiveRecord::Base\n  has_many :likes\n  has_many :users, through: :likes\n\n  include SimpleRecommender::Recommendable\n  similar_by :users\nend\n\n```\n\nNow you can call `similar_items` to find similar books based on who liked them!\n\n```ruby\nbook.similar_items(n_results: 3)\n# =\u003e [#\u003cBook id: 1840, name: \"Twilight\"\u003e,\n      #\u003cBook id: 1231, name: \"Redwall\"\u003e,\n      #\u003cBook id: 1455, name: \"Lord of the Rings\"\u003e]\n```\n\nThe items are returned in descending order of similarity. Each item also has\na `similarity` method you can call to find out how similar the items were.\n1.0 means the two items share exactly the same associations, and 0.0 means that\nthere is no overlap at all.\n\n```ruby\nbook.similar_items(n_results: 3).map(\u0026:similarity)\n# =\u003e [0.5, 0.421, 0.334]\n```\n\nYou can also decide how many results to return with the `n_results` parameter.\n\n## Roadmap\n\nThis gem is still in early development. Some changes I'm considering:\n\n* offline precomputation of recommendations for higher-volume datasets\n* similarity based on multiple associations combined with weights\n* \"user-item\" recommendation: recommend things to a user based on all of their items\n* recommendations based on numerical ratings rather than like/dislike\n* recommendations based on a weighted mix of various associations\n* MySQL support\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeoffreylitt%2Fsimple_recommender","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeoffreylitt%2Fsimple_recommender","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeoffreylitt%2Fsimple_recommender/lists"}