{"id":21905048,"url":"https://github.com/kenjyco/redis-helper","last_synced_at":"2025-04-15T23:25:09.800Z","repository":{"id":2938735,"uuid":"46906882","full_name":"kenjyco/redis-helper","owner":"kenjyco","description":"Easily store, index, and modify Python dicts in Redis (with flexible searching)","archived":false,"fork":false,"pushed_at":"2024-11-27T01:46:36.000Z","size":322,"stargazers_count":10,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-27T02:32:23.225Z","etag":null,"topics":["cli","dashboard-backend","database","easy-modeling","event-logging","kenjyco","prototyping","python","redis"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kenjyco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-26T05:54:28.000Z","updated_at":"2024-11-27T01:46:40.000Z","dependencies_parsed_at":"2022-08-08T13:00:16.855Z","dependency_job_id":"e5ff1597-fe08-44f0-b758-e1c79ebaa0c6","html_url":"https://github.com/kenjyco/redis-helper","commit_stats":{"total_commits":264,"total_committers":2,"mean_commits":132.0,"dds":0.007575757575757569,"last_synced_commit":"ee3254dcdd399fe1676c882809c563d4ac4cda28"},"previous_names":[],"tags_count":66,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenjyco%2Fredis-helper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenjyco%2Fredis-helper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenjyco%2Fredis-helper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenjyco%2Fredis-helper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kenjyco","download_url":"https://codeload.github.com/kenjyco/redis-helper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226948913,"owners_count":17707965,"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":["cli","dashboard-backend","database","easy-modeling","event-logging","kenjyco","prototyping","python","redis"],"created_at":"2024-11-28T16:27:59.556Z","updated_at":"2024-11-28T16:28:00.224Z","avatar_url":"https://github.com/kenjyco.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e Note: as of redis-helper v0.4.0, version 3.0 of redis-py is in use, which has\n\u003e backwards incompatible changes withe redis-py 2.x. See\n\u003e \u003chttps://github.com/redis/redis-py/tree/70ef9ec68f9163c86d4cace2941e2f0ae4ce8525#upgrading-from-redis-py-2x-to-30\u003e\n\n## About\n\n[redis-helper project]: https://github.com/kenjyco/redis-helper\n[beu-fork]: https://github.com/kenjyco/beu/tree/4aea6146fc5f01df3e344b9fadddf28b795dac89\n[Redis]: http://redis.io/topics/data-types-intro\n[redis-helper package]: https://pypi.python.org/pypi/redis-helper\n[request logging demo]: https://asciinema.org/a/101422?t=1:10\n[urls demo]: https://asciinema.org/a/75kl95ty9vg2jl93pfz9fbs9q?t=1:00\n[examples]: https://github.com/kenjyco/redis-helper/tree/master/examples\n[settings.ini]: https://github.com/kenjyco/redis-helper/blob/master/redis_helper/settings.ini\n[bg-helper docker tools]: https://github.com/kenjyco/bg-helper#helper-functions-in-bg_helpertools-that-use-docker-if-it-is-installed\n\nInstall redis-helper, create an instance of `redis_helper.Collection`\n(**the args/kwargs define the model**) and use the `add`, `get`, `update`,\n`delete`, and `find` methods to:\n\n- quickly store/retrieve/modify Python dicts in Redis\n- filter through indexed fields with simple/flexible find arguments\n- power real-time dashboards with metrics at a variety of time ranges\n- super-charge event logging and system debugging\n- build FAST prototypes and simulators\n- greatly simplify data access patterns throughout application\n\nSee the [request logging demo][] and [urls demo][] (with `unique_field`\ndefined). The [examples][] they reference are **short** and **easy to\nread**.\n\nThe [redis-helper project][] evolved from a [reference Python project][beu-fork]\nthat would be **easy to teach** and follow many practical best practices and\nuseful patterns.  Main purpose was to have something that was super **easy to\nconfigure** (a single `~/.config/redis-helper/settings.ini` file for multiple\napplication environments) that did cool things with [Redis][].\n\nThe [redis-helper package][] provides a `Collection` class that was designed to\nbe **easy to interact with** in the shell (for exploration, experimentation, and\ndebugging). Most methods on a `Collection` help **minimize typing** (passing\nmultiple arguments in a single delimited string when appropriate) and do \"the\nmost reasonable thing\" whenever possible.\n\nThe first time that `redis_helper` is imported, the sample\n[settings.ini][] file will be copied to the `~/.config/redis-helper`\ndirectory.\n\n```\n[default]\nimage_version = 6-alpine\n\n[dev]\ncontainer_name = redis-helper\nport = 6379\nrm = False\nredis_url = redis://localhost:6379/1\n\n[test]\ncontainer_name = redis-helper-test\nport = 6380\nrm = True\nredis_url = redis://localhost:6380/9\n```\n\nIf docker is installed to your system and your user has permission to use it,\nthe [bg-helper docker tools][] will be used to start a redis container for\ndevelopment or running tests, if Redis is not already installed locally.\n\n## (Optionally) install Redis and start server locally\n\n```\n% sudo apt-get install -y redis-server\n\nor\n\n% brew install redis\n% brew services start redis\n```\n\n## Install redis-helper\n\n- install latest tag/release of [redis-helper package][]\n\n    ```\n    % pip3 install redis-helper\n    ```\n- or, install latest commit on master of [redis-helper project][]\n\n    ```\n    % pip3 install git+git://github.com/kenjyco/redis-helper\n    ```\n\n## Intro\n\n[redis-py]: https://github.com/andymccurdy/redis-py\n[StrictRedis]: https://redis-py.readthedocs.org/en/latest/#redis.StrictRedis\n[ujson]: https://pypi.python.org/pypi/ujson\n[dict]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries\n[hash]: https://redis.io/topics/data-types#hashes\n[set]: https://redis.io/topics/data-types#sets\n[sorted set]: https://redis.io/topics/data-types#sorted-sets\n[hash commands]: http://redis.io/commands#hash\n[set commands]: https://redis.io/commands#set\n[sorted set commands]: https://redis.io/commands#sorted_set\n\n[Redis][] is a fast in-memory **data structure server**, where each stored\nobject is referenced by a key name. Objects in Redis correspond to one of\nseveral basic types, each having their own set of specialized commands to\nperform operations. The [redis Python package][redis-py] provides the\n[StrictRedis][] class, which contains methods that correspond to all of the\nRedis server commands.\n\nWhen initializing Collection objects, you must specify the \"namespace\" and\n\"name\" of the collection (which are used to create the internally used\n`_base_key` property). All Redis keys associated with a Collection will have a\nname pattern that starts with the `_base_key`.\n\n```python\nimport redis_helper as rh\n\n\nrequest_logs = rh.Collection(\n    'log',\n    'request',\n    index_fields='status, uri, host',\n    json_fields='request, response, headers'\n)\n\nurls = rh.Collection(\n    'web',\n    'url',\n    unique_field='name',\n    index_fields='domain, _type'\n)\n\nnotes = rh.Collection(\n    'input',\n    'note',\n    index_fields='topic, tag',\n    insert_ts=True\n)\n\nsample = rh.Collection(\n    'ns',\n    'sample',\n    unique_field='name',\n    index_fields='status',\n    json_fields='data',\n    rx_name='\\S{4,6}',\n    rx_status='(active|inactive|cancelled)',\n    rx_aws='[a-z]+\\-[0-9a-f]+',\n    insert_ts=True\n)\n\nuses_sample = rh.Collection(\n    'ns',\n    'uses_sample',\n    index_fields='z',\n    rx_thing='\\S{4,6}',\n    reference_fields='thing--ns:sample'\n)\n```\n\n- a `unique_field` can be specified on a collection if items in the collection\n  should not contain duplicate values for that particular field\n    - the `unique_field` cannot also be included in `json_fields` or\n      `pickle_fields`\n    - if you specify a `unique_field`, that field must exist on each item you\n      add to the collection\n- use `index_fields` to specify which fields you will want to filter on when\n  using the `find` method\n    - the values for data fields being indexed MUST be simple strings or numbers\n    - the values for data fields being indexed SHOULD NOT be long strings, as\n      the values themselves are part of the index keys\n- use `json_fields` to specify which fields should be JSON encoded before\n  insertion to Redis (using the very fast [ujson][] library)\n- use `rx_{field}` to specify a regular expression for any field with strict\n  rules for validation\n- use `reference_fields` to specify fields that reference the `unique_field` of\n  another collection\n    - uses field--basekey combos\n- use `pickle_fields` to specify which fields should be pickled before insertion\n  to Redis\n- set `insert_ts=True` to create an additional index to store insert times\n    - only do this if you are storing items that you are likely to update and\n      also likely to want to know the original insert time\n        - each time an object is updated, the score associated with the\n          `hash_id` (at the `_ts_zset_key`) is updated to the current timestamp\n        - the score associated with the `hash_id` (at the `_in_zset_key`) is\n          never updated\n\nEssentially, you can store a Python [dict][] in a Redis [hash][] and index some\nof the fields in Redis [sets][set]. The collection's `_ts_zset_key` is the Redis\nkey name for the [sorted set][] containing the `hash_id` of every hash in the\ncollection (with the `score` being a `utc_float` corresponding to the UTC time\nthe `hash_id` was added or modified).\n\n- if `insert_ts=True` was passed in when initializing the `Collection` (or\n  sub-class), then the collection will also define `self.in_zset_key` to be the\n  Redis key name for the sorted set (for `hash_id` and `utc_float` of insert\n  time)\n\n```python\nrequest_logs.add(\n    method='get',\n    status=400,\n    host='blah.net',\n    uri='/info',\n    request={'x': 50, 'y': 100},\n    response={'error': 'bad request'},\n)\n\nurls.add(\n    name='redis-helper github',\n    url='https://github.com/kenjyco/redis-helper',\n    domain='github.com',\n    _type='repo',\n)\n```\n\nThe `get` method is a wrapper to [hash commands][] `hget`, `hmget`, or\n`hgetall`. The actual hash command that gets called is determined by the number of\nfields requested.\n\n- a Python dict is typically returned from `get`\n- if `item_format` is specified, a string will be returned matching that format\n  instead\n\n```python\nrequest_logs.get('log:request:1')\nrequest_logs.get('log:request:1', 'host,status')\nrequest_logs.get('log:request:1', item_format='{status} for {host}{uri}')\nrequest_logs.get_by_position(0, item_format='{status} for {host}{uri}')\nurls.get_by_position(-1, 'domain,url')\nurls.get_by_unique_value('redis-helper github', item_format='{url} points to a {_type}')\n```\n\n- the `get_by_position` and `get_by_unique_value` methods are wrappers to `get`\n    - the `get_by_unique_value` method is only useful if a `unique_field` was\n      set on the Collection\n\nThe `find` method allows you to return data for items in the collection that\nmatch some set of search criteria. Multiple search terms (i.e.\n`index_field:value` pairs) maybe be passed in the `terms` parameter, as long as they are\nseparated by one of `,` `;` `|`. Any fields specified in the `get_fields`\nparameter are passed along to the `get` method (when the actual fetching takes\nplace).\n\n- when using `terms`, all terms that include the same field will be treatead\n  like an \"or\" (union of related sets), then the intersection of different sets\n  will be computed\n- see the Redis [set commands][] and [sorted set commands][]\n\nThere are many options for specifying time ranges in the `find` method\nincluding:\n\n- `since` and `until` when specifying `num:unit` strings (i.e. 15:seconds,\n  1.5:weeks, etc)\n- `start_ts` and `end_ts` when specifying timestamps with a form between `YYYY`\n  and `YYYY-MM-DD HH:MM:SS.f`\n- `start` and `end` when specifying a `utc_float`\n- for `since`, `until`, `start_ts`, and `end_ts`, multiple values may be passed\n  in the string, as long as they are separated by one of `,` `;` `|`.\n    - when multiple time ranges are specified, the `find` method will determine\n      all reasonable combinations and return a result-set per combination\n      (instead of returning a list of items, returns a dict of list of items)\n\nIf `count=True` is specified, the number of results matching the search criteria\nare returned instead of the actual results\n\n- if there are multiple time ranges specified, counts will be returned for each\n  combination\n\n```python\nrequest_logs.find('status:400, host:blah.net', get_fields='uri,error')\nrequest_logs.find(since='1:hr, 30:min', until='15:min, 5:min')\nrequest_logs.find(count=True, since='1:hr, 30:min', until='15:min, 5:min')\nurls.find(count=True, since='1:hr, 30:min, 10:min, 5:min, 1:min')\nurls.find(start_ts='2017-02-03', end_ts='2017-02-03 7:15:00')\nurls.find(start_ts='2017-02-03', item_format='{_ts} -\u003e {_id}')\n```\n\nThe `update` method allows you to change values for some fields (modifying the\n`unique_field`, when it is specified, is not allowed).\n\n- every time a field is modified for a particular `hash_id`, the previous value\n  and score (timestamp) are stored in a Redis hash\n- the `old_data_for_hash_id` or `old_data_for_unique_value` methods can be used\n  to retrieve the history of all changes for a `hash_id`\n\n```python\nurls.update('web:url:1', _type='fancy', notes='this is a fancy url')\nurls.old_data_for_hash_id('web:url:1')\nurls.old_data_for_unique_value('redis-helper github')\n```\n\nThe `load_ref_data` option on `get`, `get_by_unique_value`, or `find` methods\nallow you to load the referenced data object from the other collection (where\n`reference_fields` are specified)\n\n```python\nIn [1]: sample.add(name='hello', aws='ami-0ad5743816d822b81', status='active')\nOut[1]: 'ns:sample:1'\n\nIn [2]: uses_sample.add(thing='hello', z=500, y=True)\nOut[2]: 'ns:uses_sample:1'\n\nIn [3]: uses_sample.get('ns:uses_sample:1')\nOut[3]: {'thing': 'hello', 'z': 500, 'y': True}\n\nIn [4]: uses_sample.get('ns:uses_sample:1', load_ref_data=True)\nOut[4]:\n{'thing': {'name': 'hello',\n  'aws': 'ami-0ad5743816d822b81',\n  'status': 'active',\n  '_id': 'ns:sample:1',\n  '_ts': 20201028210044.875},\n 'z': 500,\n 'y': True}\n\nIn [5]: uses_sample.add(thing='byebye', z=100, y=True)\nOut[5]: 'ns:uses_sample:2'\n\nIn [6]: uses_sample.get('ns:uses_sample:2', load_ref_data=True)\nOut[6]: {'thing': 'byebye', 'z': 100, 'y': True}\n```\n\n## Tip\n\nThere may be times where you want to use redis-helper (if it's already\ninstalled), but don't want to make it an explicit requirement of your project.\nIn cases like this you can do the following:\n\n```\ntry:\n    import redis_helper as rh\n    from redis import ConnectionError as RedisConnectionError\nexcept (ImportError, ModuleNotFoundError):\n    SomeCollection = None\nelse:\n    try:\n        SomeCollection = rh.Collection(\n            ...\n        )\n    except RedisConnectionError:\n        SomeCollection = None\n```\n\nThen in whatever function, you can just do:\n\n```\ndef some_func():\n    if SomeCollection is None:\n        return\n\n    # Do stuff with SomeCollection\n```\n\n## Local development setup\n\n[dev-setup.bash]: https://github.com/kenjyco/redis-helper/blob/master/dev-setup.bash\n\n```\n% git clone https://github.com/kenjyco/redis-helper\n% cd redis-helper\n% ./dev-setup.bash\n```\n\nThe [dev-setup.bash][] script will create a virtual environment in the\n`./venv` directory with extra dependencies (ipython, pdbpp, pytest), then copy\n`settings.ini` to the `~/.config/redis-helper` directory.\n\n## Running tests in development setup\n\n[setup.cfg]: https://github.com/kenjyco/redis-helper/blob/master/setup.cfg\n[pdb++]: https://pypi.python.org/pypi/pdbpp/\n[debugging section]: https://github.com/kenjyco/redis-helper#settings-environments-testing-and-debugging\n[project code]: https://github.com/kenjyco/redis-helper/tree/master/redis_helper\n[test code]: https://github.com/kenjyco/redis-helper/tree/master/tests\n\nThe [setup.cfg][] file contains the options for `py.test`, currently\n`-vsx -rs --pdb`.\n\nThe `-vsx -rs --pdb` options will run tests in a verbose manner and output the\nreason why tests were skipped (if any were skipped). If there are any failing\ntests, `py.test` will stop on the first failure and drop you into a [pdb++][]\ndebugger session.\n\nSee the [debugging section][] of the README for tips on using the debugger and\nsetting breakpoints (in the actual [project code][], or in the [test code][]).\n\n```\n% venv/bin/py.test\n```\n\nor\n\n```\n% venv/bin/python3 setup.py test\n```\n\n\u003e Note: This option requires `setuptools` to be installed.\n\n## Usage\n\nThe `rh-download-examples`, `rh-download-scripts`, `rh-notes`, and `rh-shell`\nscripts are provided.\n\n```\n$ venv/bin/rh-download-examples --help\nUsage: rh-download-examples [OPTIONS] [DIRECTORY]\n\n  Download redis-helper example files from github\n\nOptions:\n  --help  Show this message and exit.\n\n$ venv/bin/rh-download-scripts --help\nUsage: rh-download-scripts [OPTIONS] [DIRECTORY]\n\n  Download redis-helper script files from github\n\nOptions:\n  --help  Show this message and exit.\n\n$ venv/bin/rh-notes --help\nUsage: rh-notes [OPTIONS] [TOPIC]\n\n  Prompt user to enter notes (about a topic) until finished; or review notes\n\nOptions:\n  -c, --ch TEXT  string appended to the topic (default \"\u003e \")\n  -s, --shell    Start an ipython shell to inspect the notes collection\n  --help         Show this message and exit.\n\n$ venv/bin/rh-shell --help\nUsage: rh-shell [OPTIONS]\n\n  Interactively select a Collection model and start ipython shell\n\nOptions:\n  --help  Show this message and exit.\n```\n\n```python\n\u003e\u003e\u003e import redis_helper as rh\n\u003e\u003e\u003e collection = rh.Collection(..., index_fields='field1, field3')\n\u003e\u003e\u003e hash_id = collection.add(field1='', field2='', field3='', ...)\n\u003e\u003e\u003e collection.add(...)\n\u003e\u003e\u003e collection.add(...)\n\u003e\u003e\u003e collection.update(hash_id, field1='', field4='', ...)\n\u003e\u003e\u003e change_history = collection.old_data_for_hash_id(hash_id)\n\u003e\u003e\u003e data = collection.get(hash_id)\n\u003e\u003e\u003e some_data = collection.get(hash_id, 'field1, field3')\n\u003e\u003e\u003e results = collection.find(...)\n\u003e\u003e\u003e results2 = collection.find('field1:val, field3:val', ...)\n\u003e\u003e\u003e results3 = collection.find(..., get_fields='field2, field4')\n\u003e\u003e\u003e counts = collection.find(count=True, ...)\n\u003e\u003e\u003e top_indexed = collection.index_field_info()\n\u003e\u003e\u003e collection.delete(hash_id, ...)\n```\n\n## Basics - Part 1 (request logging demo)\n\n[rh-basics-1 1:10]: https://asciinema.org/a/101422?t=1:10\n[rh-basics-1 3:14]: https://asciinema.org/a/101422?t=3:14\n[rh-basics-1 4:22]: https://asciinema.org/a/101422?t=4:22\n[rh-basics-1 6:11]: https://asciinema.org/a/101422?t=6:11\n[rh-basics-1 7:00]: https://asciinema.org/a/101422?t=7:00\n[rh-basics-1 8:37]: https://asciinema.org/a/101422?t=8:37\n[rh-basics-1 10:33]: https://asciinema.org/a/101422?t=10:33\n[rh-basics-1 11:27]: https://asciinema.org/a/101422?t=11:27\n[rh-basics-1 14:30]: https://asciinema.org/a/101422?t=14:30\n[rh-basics-1 15:54]: https://asciinema.org/a/101422?t=15:54\n[request_logs.py]: https://github.com/kenjyco/redis-helper/blob/master/examples/request_logs.py\n\n[Demo][request logging demo] bookmarks:\n\n- [1:10][rh-basics-1 1:10] is when the `ipython` session is started with\n  `venv/bin/ipython -i request_logs.py`\n- [3:14][rh-basics-1 3:14] is when a second `ipython` session is started (in a\n  separate tmux pane) to simulate a steady stream of requests with\n  `slow_trickle_requests(randomsleep=True, show=True)`\n- [4:22][rh-basics-1 4:22] is when the `index_field_info` method is used to\n  get the latest counts of top indexed items\n- [6:11][rh-basics-1 6:11] is when `slow_trickle_requests(.001)` is run to\n  simulate a large quick burst in traffic\n- [7:00][rh-basics-1 7:00] is when multiple values are passed in the `since`\n  argument of `find`... `request_logs.find(count=True, since='5:min, 1:min,\n  30:sec')`\n- [8:37][rh-basics-1 8:37] is when `get` and `get_by_position` methods are used\n  with a variety of arguments to change the structure of what's returned\n- [10:33][rh-basics-1 10:33] is when the `redis_helper.ADMIN_TIMEZONE` is\n  changed at run time from `America/Chicago` to `Europe/London`\n- [11:27][rh-basics-1 11:27] is when `find` is used with a variety of arguments\n  to change the structure of what's returned\n- [14:30][rh-basics-1 14:30] is when `find` is used with multiple search terms\n  and multiple `since` values... `request_logs.find('host:dogs.com,\n  uri:/breeds', count=True, since='5:min, 1:min, 10:sec')`\n- [15:54][rh-basics-1 15:54] is when the `update` method is used to modify data\n  and change history is retrieved with the `old_data_for_hash_id` method\n\nThe first demo walks through the following:\n\n- creating a virtual environment, installing redis-helper, and downloading\n  example files\n\n    ```\n    $ python3 -m venv venv\n    $ venv/bin/pip3 install redis-helper ipython\n    $ venv/bin/rh-download-examples\n    $ cat ~/.config/redis-helper/settings.ini\n    $ venv/bin/ipython -i request_logs.py\n    ```\n- using the sample `Collection` defined in [request_logs.py][] to\n    - show values of some properties on a `Collection`\n        - `redis_helper.Collection._base_key`\n        - `redis_helper.Collection.now_pretty`\n        - `redis_helper.Collection.now_utc_float`\n        - `redis_helper.Collection.keyspace`\n        - `redis_helper.Collection.size`\n        - `redis_helper.Collection.first`\n        - `redis_helper.Collection.last`\n    - show values of some settings from `redis_helper`\n        - `redis_helper.APP_ENV`\n        - `redis_helper.REDIS_URL`\n        - `redis_helper.REDIS`\n        - `redis_helper.SETTINGS_FILE`\n        - `redis_helper.ADMIN_TIMEZONE`\n    - show output from some methods on a `Collection`\n        - `redis_helper.Collection.index_field_info()`\n        - `redis_helper.Collection.find()`\n        - `redis_helper.Collection.find(count=True)`\n        - `redis_helper.Collection.find(count=True, since='30:sec')`\n        - `redis_helper.Collection.find(since='30:sec')`\n        - `redis_helper.Collection.find(since='30:sec', admin_fmt=True)`\n        - `redis_helper.Collection.find(count=True, since='5:min, 1:min, 30:sec')`\n        - `redis_helper.Collection.find('index_field:value')`\n        - `redis_helper.Collection.find('index_field:value', all_fields=True, limit=2)`\n        - `redis_helper.Collection.find('index_field:value', all_fields=True, limit=2, admin_fmt=True, item_format='{_ts} -\u003e {_id}')`\n        - `redis_helper.Collection.find('index_field:value', get_fields='field1, field2', include_meta=False)`\n        - `redis_helper.Collection.find('index_field1:value1, index_field2:value2', count=True)`\n        - `redis_helper.Collection.find('index_field1:value1, index_field2:value2', count=True, since='5:min, 1:min, 10:sec')`\n        - `redis_helper.Collection.get(hash_id)`\n        - `redis_helper.Collection.get(hash_id, 'field1,field2,field3')`\n        - `redis_helper.Collection.get(hash_id, include_meta=True)`\n        - `redis_helper.Collection.get(hash_id, include_meta=True, fields='field1, field2')`\n        - `redis_helper.Collection.get(hash_id, include_meta=True, item_format='{_ts} -\u003e {_id}')`\n        - `redis_helper.Collection.get_by_position(0)`\n        - `redis_helper.Collection.get_by_position(0, include_meta=True, admin_fmt=True)`\n        - `redis_helper.Collection.update(hash_id, field1='value1', field2='value2')`\n        - `redis_helper.Collection.old_data_for_hash_id(hash_id)`\n\n## Basics - Part 2 (urls demo, with unique field)\n\n[urls.py]: https://github.com/kenjyco/redis-helper/blob/master/examples/urls.py\n\n[Demo][urls demo] bookmarks:\n\n- `TODO`\n\nThe second demo walks through the following:\n\n- using the sample `Collection` defined in [urls.py][] to\n    - `TODO`\n\n## Settings, environments, testing, and debugging\n\nTo trigger a debugger session at a specific place in the [project code][],\ninsert the following, one line above where you want to inspect\n\n```\nimport pdb; pdb.set_trace()\n```\n\nTo start the debugger inside [test code][], use\n\n```\npytest.set_trace()\n```\n\n- use `(l)ist` to list context lines\n- use `(n)ext` to move on to the next statement\n- use `(s)tep` to step into a function\n- use `(c)ontinue` to continue to next break point (i.e. `set_trace()` lines in\n  your code)\n- use `sticky` to toggle sticky mode (to constantly show the currently executing\n  code as you move through with the debugger)\n- use `pp` to pretty print a variable or statement\n\nIf the redis server at `redis_url` (in the **test section** of\n`~/.config/redis-server/settings.ini`) is not running or is not empty, redis\nserver tests will be skipped.\n\nUse the `APP_ENV` environment variable to specify which section of the\n`settings.ini` file your settings will be loaded from. Any settings in the\n`default` section can be overwritten if explicity set in another section.\n\n- if no `APP_ENV` is explicitly set, `dev` is assumed\n- the `APP_ENV` setting is overwritten to be `test` no matter what was set when\n  calling `py.test` tests\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkenjyco%2Fredis-helper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkenjyco%2Fredis-helper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkenjyco%2Fredis-helper/lists"}