{"id":13879753,"url":"https://github.com/ProctorU/squint","last_synced_at":"2025-07-16T15:33:01.853Z","repository":{"id":56469421,"uuid":"91132483","full_name":"ProctorU/squint","owner":"ProctorU","description":"Search PostgreSQL jsonb and hstore columns","archived":false,"fork":false,"pushed_at":"2020-11-05T15:08:07.000Z","size":82,"stargazers_count":26,"open_issues_count":1,"forks_count":3,"subscribers_count":31,"default_branch":"master","last_synced_at":"2024-11-14T19:45:31.607Z","etag":null,"topics":["activerecord","hstore","hstore-columns","jsonb","postgresql","proctoru","ruby-on-rails","sql","storext-attribute"],"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/ProctorU.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-12T21:57:21.000Z","updated_at":"2020-11-27T18:17:55.000Z","dependencies_parsed_at":"2022-08-15T19:20:35.683Z","dependency_job_id":null,"html_url":"https://github.com/ProctorU/squint","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProctorU%2Fsquint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProctorU%2Fsquint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProctorU%2Fsquint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProctorU%2Fsquint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ProctorU","download_url":"https://codeload.github.com/ProctorU/squint/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226143895,"owners_count":17580245,"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":["activerecord","hstore","hstore-columns","jsonb","postgresql","proctoru","ruby-on-rails","sql","storext-attribute"],"created_at":"2024-08-06T08:02:31.639Z","updated_at":"2024-11-24T08:31:44.995Z","avatar_url":"https://github.com/ProctorU.png","language":"Ruby","readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://twitter.com/ProctorUEng\"\u003e\n    \u003cimg src=\"https://s3-us-west-2.amazonaws.com/dev-team-resources/squint-wordmark.svg\" width=198 height=72\u003e\n  \u003c/a\u003e\n\n  \u003cp align=\"center\"\u003e\n    Search PostgreSQL \u003ccode\u003ejsonb\u003c/code\u003e and \u003ccode\u003ehstore\u003c/code\u003e columns.\n  \u003c/p\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n\u003e Full database searching inside columns containing semi-structured data like `json`,\n`jsonb` and `hstore`. \u003cstrong\u003eCompatible with the awesome\n\u003ca href=\"https://github.com/G5/storext\"\u003estorext\u003c/a\u003e gem\u003c/strong\u003e.\n\n## Table of contents\n\n- [Status](#status)\n- [Quick start](#quick-start)\n- [Performance](#performance)\n- [Storext attributes](#storext-attributes)\n- [Developing](#developing)\n- [Contributors](#contributors)\n- [Credits](#credits)\n\n## Status\n[![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors)\n[![CircleCI](https://circleci.com/gh/ProctorU/squint.svg?style=svg)](https://circleci.com/gh/ProctorU/squint)\n\n## Quick Start\n\nAdd to your Gemfile:\n\n```ruby\ngem 'squint'\n```\n\nInclude it in your models:\n\n```ruby\nclass Post \u003c ActiveRecord::Base\n  include Squint\n  # ...\nend\n```\n\nAssuming a table with the following structure:\n```\n                                           Table \"public.posts\"\n       Column              |            Type             |                     Modifiers\n---------------------------+-----------------------------+----------------------------------------------------\n id                        | integer                     | not null default nextval('posts_id_seq'::regclass)\n title                     | character varying           |\n body                      | character varying           |\n request_info              | jsonb                       |\n properties                | hstore                      |\n storext_jsonb_attributes  | jsonb                       |\n storext_hstore_attributes | jsonb                       |\n created_at                | timestamp without time zone | not null\n updated_at                | timestamp without time zone | not null\nIndexes:\n    \"posts_pkey\" PRIMARY KEY, btree (id)\n```\n\nIn your code use queries like:\n```ruby\nPost.where(properties: { referer: 'http://example.com/one' } )\n# SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"properties\"-\u003e'referer' = 'http://example.com/one'\n\nPost.where(properties: { referer: nil } )\n# SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"properties\"-\u003e'referer' IS NULL\n\nPost.where(properties: { referer: ['http://example.com/one',nil] } )\n# SELECT \"posts\".* FROM \"posts\" WHERE (\"posts\".\"properties\"-\u003e'referer' = 'http://example.com/one'\n#                                   OR \"posts\".\"properties\"-\u003e'referer' IS NULL)\n\nPost.where(request_info: { referer: ['http://example.com/one',nil] } )\n# SELECT \"posts\".* FROM \"posts\" WHERE (\"posts\".\"request_info\"-\u003e\u003e'referer' = 'http://example.com/one'\n#                                   OR \"posts\".\"request_info\"-\u003e\u003e'referer' IS NULL)\n```\n\nSquint only operates on json, jsonb and hstore columns.   ActiveRecord\nwill throw a StatementInvalid exception like always if the column type is unsupported by\nSquint.\n\n```ruby\nPost.where(title: { not_there: \"any value will do\" } )\n```\n\n```\nActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table \"title\"\nLINE 1: SELECT COUNT(*) FROM \"posts\" WHERE \"title\".\"not_there\" = 'an...\n                                           ^\n: SELECT COUNT(*) FROM \"posts\" WHERE \"title\".\"not_there\" = 'any value will do'\n```\n\n## Performance\nTo get the most performance out searching jsonb/hstore attributes, add a GIN (preferred) or\nGIST index to those columns.   Find out more\n[here](https://www.postgresql.org/docs/9.5/static/textsearch-indexes.html)\n\nTL;DR:\n\nSQL: 'CREATE INDEX name ON table USING GIN (column);'\n\nRails Migration: `add_index(:table, :column_name, using: 'gin')`\n\n\n## Storext attributes\nAssuming the database schema above and a model like so:\n```ruby\nclass Post \u003c ActiveRecord::Base\n  include Storext.model\n  include Squint\n\n  store_attribute :storext_jsonb_attributes, :zip_code, String, default: '90210'\n  store_attribute :storext_jsonb_attributes, :friend_count, Integer, default: 0\nend\n```\n\nExample using StoreXT with a default value:\n```ruby\nPost.where(storext_jsonb_attributes: { zip_code: '90210' } )\n# -- jsonb\n# SELECT \"posts\".* FROM \"posts\" WHERE (\"posts\".\"storext_jsonb_attributes\"-\u003e\u003e'zip_code' = '90210' OR\n#                                     ((\"posts\".\"storext_jsonb_attributes\" ? 'zip_code') IS NULL OR\n#                                      (\"posts\".\"storext_jsonb_attributes\" ? 'zip_code') = FALSE))\n# -- hstore\n# SELECT \"posts\".* FROM \"posts\" WHERE (\"posts\".\"storext_hstore_attributes\"-\u003e'zip_code' = '90210' OR\n#                                     ((exist(\"posts\".\"storext_hstore_attributes\", 'zip_code') = FALSE) OR\n#                                       exist(\"posts\".\"storext_hstore_attributes\", 'zip_code') IS NULL))\n#\n#\n```\nIf (as in the example above) the default value for the StoreXT attribute is specified, then extra\nchecks for missing column ( `(\"posts\".\"storext_jsonb_attributes\" ? 'zip_code') IS NULL` ) or\nmissing key ( `(\"posts\".\"storext_jsonb_attributes\" ? 'zip_code') = FALSE)` ) are added\n\nWhen non-default storext values are specified, these extra checks won't be added.\n\nThe Postgres SQL for jsonb and hstore is different.   No support for checking for missing `json`\ncolumns exists, so don't use those with StoreXT + Squint\n\n## Developing\n\n1. Thank you!\n1. Clone the repository\n1. `bundle`\n1. `bundle exec rake --rakefile test/dummy/Rakefile db:setup` # create the db for tests\n1. `bundle exec rake`   # run the tests\n1. make your changes in a thoughtfully named branch\n1. ensure good test coverage\n1. submit a Pull Request\n\n## Contributors\n\nThanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n| [\u003cimg src=\"https://avatars2.githubusercontent.com/u/864581?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eKevin Brown\u003c/sub\u003e](https://github.com/chevinbrown)\u003cbr /\u003e[🎨](#design-chevinbrown \"Design\") [👀](#review-chevinbrown \"Reviewed Pull Requests\") | [\u003cimg src=\"https://avatars2.githubusercontent.com/u/1741179?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eAndrew Fomera\u003c/sub\u003e](http://andrewfomera.com)\u003cbr /\u003e[👀](#review-king601 \"Reviewed Pull Requests\") [💻](https://github.com/ProctorU/squint/commits?author=king601 \"Code\") | [\u003cimg src=\"https://avatars2.githubusercontent.com/u/708692?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eRyan T. Hosford\u003c/sub\u003e](https://github.com/rthbound)\u003cbr /\u003e[💻](https://github.com/ProctorU/squint/commits?author=rthbound \"Code\") | [\u003cimg src=\"https://avatars2.githubusercontent.com/u/1785682?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eMatthew Jaeh\u003c/sub\u003e](https://github.com/Jaehdawg)\u003cbr /\u003e[🎨](#design-Jaehdawg \"Design\") [👀](#review-Jaehdawg \"Reviewed Pull Requests\") | [\u003cimg src=\"https://avatars0.githubusercontent.com/u/3933204?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eJustin Licata\u003c/sub\u003e](https://twitter.com/justinlicata)\u003cbr /\u003e[💻](https://github.com/ProctorU/squint/commits?author=licatajustin \"Code\") [🎨](#design-licatajustin \"Design\") [📖](https://github.com/ProctorU/squint/commits?author=licatajustin \"Documentation\") [👀](#review-licatajustin \"Reviewed Pull Requests\") | [\u003cimg src=\"https://avatars3.githubusercontent.com/u/24704300?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eKyle Miracle\u003c/sub\u003e](https://github.com/kmiracle86)\u003cbr /\u003e[🐛](https://github.com/ProctorU/squint/issues?q=author%3Akmiracle86 \"Bug reports\") [👀](#review-kmiracle86 \"Reviewed Pull Requests\") | [\u003cimg src=\"https://avatars2.githubusercontent.com/u/97011?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eDavid H. Wilkins\u003c/sub\u003e](http://conecuh.com)\u003cbr /\u003e[💬](#question-dwilkins \"Answering Questions\") [🐛](https://github.com/ProctorU/squint/issues?q=author%3Adwilkins \"Bug reports\") [💻](https://github.com/ProctorU/squint/commits?author=dwilkins \"Code\") [🎨](#design-dwilkins \"Design\") [📖](https://github.com/ProctorU/squint/commits?author=dwilkins \"Documentation\") [💡](#example-dwilkins \"Examples\") [👀](#review-dwilkins \"Reviewed Pull Requests\") [⚠️](https://github.com/ProctorU/squint/commits?author=dwilkins \"Tests\") |\n| :---: | :---: | :---: | :---: | :---: | :---: | :---: |\n| [\u003cimg src=\"https://avatars3.githubusercontent.com/u/19173815?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eJay Wright\u003c/sub\u003e](https://github.com/TheJayWright)\u003cbr /\u003e[👀](#review-TheJayWright \"Reviewed Pull Requests\") | [\u003cimg src=\"https://avatars1.githubusercontent.com/u/4067?s=460\u0026u=cb404cc0f1737c2fc53411e300cc8e158ef29295\u0026v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eJames Cook\u003c/sub\u003e](https://github.com/jamescook)\u003cbr /\u003e[💻](https://github.com/ProctorU/squint/commits?author=jamescook \"Code\") [⚠️](https://github.com/ProctorU/squint/commits?author=jamescook \"Tests\") [👀](#review-jamescook \"Reviewed Pull Requests\") |\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!\n\n## Credits\n\nSquint is maintained and funded by [ProctorU](https://twitter.com/ProctorUEng).\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://twitter.com/ProctorUEng\"\u003e\n    \u003cimg src=\"https://s3-us-west-2.amazonaws.com/dev-team-resources/procki-eyes.svg\" width=108 height=72\u003e\n  \u003c/a\u003e\n\n  \u003ch3 align=\"center\"\u003e\n    \u003ca href=\"https://twitter.com/ProctorUEng\"\u003eProctorU Engineering \u0026 Design\u003c/a\u003e\n  \u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    A simple online proctoring service that allows you to take exams or certification tests at home.\n  \u003c/p\u003e\n\u003c/p\u003e\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FProctorU%2Fsquint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FProctorU%2Fsquint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FProctorU%2Fsquint/lists"}