summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena Kolevska <elena-kolevska@users.noreply.github.com>2023-04-20 14:05:49 +0200
committerGitHub <noreply@github.com>2023-04-20 15:05:49 +0300
commitcf07c53eddbcdb4328bf3e7fc0a3c82b74171f44 (patch)
treeb40b878b46f64c4ffb4992541cd33cbcdba8eb2b
parentff67087a2e097c4489d6ca4a7239975ce6db3725 (diff)
downloadredis-py-cf07c53eddbcdb4328bf3e7fc0a3c82b74171f44.tar.gz
Redis.io website examples (#2708)
Co-authored-by: Igor Malinovskiy <igor.malinovskiy@redis.com> Co-authored-by: Chayim I. Kirshen <c@kirshen.com>
-rw-r--r--.github/workflows/doctests.yml42
-rw-r--r--docs/examples/bikes_1/bike_setup.py36
-rw-r--r--docs/examples/bikes_1/example.json4
-rw-r--r--docs/examples/bikes_2/bike_index.py41
-rw-r--r--docs/examples/bikes_2/example.json4
-rw-r--r--docs/examples/bikes_3/bike_search.py46
-rw-r--r--docs/examples/bikes_3/example.json4
-rw-r--r--docs/examples/bikes_4/bike_advanced_search.py53
-rw-r--r--docs/examples/bikes_4/example.json4
-rw-r--r--docs/examples/json_bikes/bike_advanced_search.py53
-rw-r--r--docs/examples/json_bikes/bike_index.py41
-rw-r--r--docs/examples/json_bikes/bike_search.py46
-rw-r--r--docs/examples/json_bikes/bike_setup.py36
-rw-r--r--docs/examples/json_search/example.json4
-rw-r--r--docs/examples/json_search/main.py36
-rw-r--r--doctests/README.md31
-rw-r--r--doctests/bike_advanced_search.py135
-rw-r--r--doctests/bike_index.py109
-rw-r--r--doctests/bike_search.py119
-rw-r--r--doctests/bike_setup.py30
-rw-r--r--doctests/run_examples.sh15
-rw-r--r--doctests/string_set_get.py20
22 files changed, 501 insertions, 408 deletions
diff --git a/.github/workflows/doctests.yml b/.github/workflows/doctests.yml
new file mode 100644
index 0000000..0c56e5e
--- /dev/null
+++ b/.github/workflows/doctests.yml
@@ -0,0 +1,42 @@
+name: Documentation Tests
+
+on:
+ push:
+ pull_request:
+
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ doctests:
+ runs-on: ubuntu-latest
+ services:
+ redis-stack:
+ image: redis/redis-stack-server:latest
+ options: >-
+ --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
+ ports:
+ - 6379:6379
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
+ with:
+ python-version: 3.9
+ cache: 'pip'
+ - run: |
+ sudo apt update
+ sudo apt install -y redis-tools
+ - name: lint check
+ run: |
+ pip install -r dev_requirements.txt
+ pip install -r requirements.txt
+ isort --check-only --diff doctests/*.py
+ black --target-version py39 --check --diff doctests/*.py
+
+ - name: run tests
+ run: |
+ python setup.py build
+ python setup.py install
+ sh doctests/run_examples.sh
diff --git a/docs/examples/bikes_1/bike_setup.py b/docs/examples/bikes_1/bike_setup.py
deleted file mode 100644
index 4aea417..0000000
--- a/docs/examples/bikes_1/bike_setup.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-# a single bike to demonstrate the basics
-bike1 = {
- "model": "Hyperion",
- "brand": "Velorim",
- "price": 844,
- "type": "Enduro bikes",
- "specs": {
- "material": "full-carbon",
- "weight": 8.7
- },
- "description": "This is a mid-travel trail slayer that is a fantastic daily driver or one bike quiver. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you\"re now getting DT Swiss R470 rims with the Formula hubs. Put it all together and you get a bike that helps redefine what can be done for this price."
-}
-
-r.json().set("bikes:1", "$", bike1)
-
-r.json().get("bikes:1", "$.model")
-r.json().get("bikes:1", "$.specs.material")
-
-r.json().set("bikes:1", "$.model", "Hyperion1")
-r.json().get("bikes:1", "$.model") \ No newline at end of file
diff --git a/docs/examples/bikes_1/example.json b/docs/examples/bikes_1/example.json
deleted file mode 100644
index 6b4ce1e..0000000
--- a/docs/examples/bikes_1/example.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "id": "bike_setup",
- "file": "bike_setup.py"
-}
diff --git a/docs/examples/bikes_2/bike_index.py b/docs/examples/bikes_2/bike_index.py
deleted file mode 100644
index d8945f1..0000000
--- a/docs/examples/bikes_2/bike_index.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-bikes = [{"model": "Ariel", "brand": "Velorim", "price": 2098, "type": "Road bikes", "specs": {"material": "carbon", "weight": 10.9}, "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability."},{"model": "Makemake", "brand": "Breakout", "price": 4551, "type": "Commuter bikes", "specs": {"material": "carbon", "weight": 12.9}, "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "BikeShind", "price": 2637, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 7.3}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability."},{"model": "Tethys", "brand": "Classic wheels", "price": 2018, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 15.7}, "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides."},{"model": "Tethys", "brand": "ScramBikes", "price": 3344, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 14.7}, "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get."},{"model": "Deimos", "brand": "Bold bicycles", "price": 2652, "type": "Commuter bikes", "specs": {"material": "aluminium", "weight": 13.7}, "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "ScramBikes", "price": 2707, "type": "Enduro bikes", "specs": {"material": "full-carbon", "weight": 11.8}, "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost."},{"model": "Mars", "brand": "7th Generation", "price": 2206, "type": "Kids mountain bikes", "specs": {"material": "aluminium", "weight": 8.9}, "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden."},{"model": "Millenium-falcon", "brand": "Breakout", "price": 826, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 9.0}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership."}]
-
-count = 0
-for bike in bikes:
- r.json().set(f"bikes:{count}", "$", bike)
- count += 1
-
-# define the fields for a bike
-bike_schema = [
- TextField("$.model", as_name="model", sortable=True, no_stem=True),
- TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
- NumericField("$.price", as_name="price", sortable=True),
- TagField("$.type", as_name="type"),
- TagField("$.specs.material", as_name="material"),
- NumericField("$.specs.weight", as_name="weight", sortable=True),
- TextField("$.description", as_name="description")
- ]
-
-# define index information
-schema_info = IndexDefinition(
- index_type=IndexType.JSON,
- prefix=["bikes:"])
-
-# create the index
-r.ft("idx:bikes").create_index(bike_schema,definition=schema_info) \ No newline at end of file
diff --git a/docs/examples/bikes_2/example.json b/docs/examples/bikes_2/example.json
deleted file mode 100644
index 3552c91..0000000
--- a/docs/examples/bikes_2/example.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "id": "bike_indexing_example",
- "file": "bike_index.py"
-}
diff --git a/docs/examples/bikes_3/bike_search.py b/docs/examples/bikes_3/bike_search.py
deleted file mode 100644
index 1093547..0000000
--- a/docs/examples/bikes_3/bike_search.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-bikes = [{"model": "Ariel", "brand": "Velorim", "price": 2098, "type": "Road bikes", "specs": {"material": "carbon", "weight": 10.9}, "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability."},{"model": "Makemake", "brand": "Breakout", "price": 4551, "type": "Commuter bikes", "specs": {"material": "carbon", "weight": 12.9}, "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "BikeShind", "price": 2637, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 7.3}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability."},{"model": "Tethys", "brand": "Classic wheels", "price": 2018, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 15.7}, "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides."},{"model": "Tethys", "brand": "ScramBikes", "price": 3344, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 14.7}, "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get."},{"model": "Deimos", "brand": "Bold bicycles", "price": 2652, "type": "Commuter bikes", "specs": {"material": "aluminium", "weight": 13.7}, "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "ScramBikes", "price": 2707, "type": "Enduro bikes", "specs": {"material": "full-carbon", "weight": 11.8}, "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost."},{"model": "Mars", "brand": "7th Generation", "price": 2206, "type": "Kids mountain bikes", "specs": {"material": "aluminium", "weight": 8.9}, "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden."},{"model": "Millenium-falcon", "brand": "Breakout", "price": 826, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 9.0}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership."}]
-
-count = 0
-for bike in bikes:
- r.json().set(f"bikes:{count}", "$", bike)
- count += 1
-
-# define the fields for a bike
-bike_schema = [
- TextField("$.model", as_name="model", sortable=True, no_stem=True),
- TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
- NumericField("$.price", as_name="price", sortable=True),
- TagField("$.type", as_name="type"),
- TagField("$.specs.material", as_name="material"),
- NumericField("$.specs.weight", as_name="weight", sortable=True),
- TextField("$.description", as_name="description")
- ]
-
-# define index information
-schema_info = IndexDefinition(
- index_type=IndexType.JSON,
- prefix=["bikes:"])
-
-# create the index
-r.ft("idx:bikes").create_index(bike_schema,definition=schema_info)
-
-r.ft("idx:bikes").search(Query("@type:{eBikes}"))
-r.ft("idx:bikes").search(Query("@type:{eBikes} @price:[200 1200]").return_fields("model", "type", "price"))
-r.ft("idx:bikes").search(Query("mudguards @type:{Mountain bikes} @price:[1000 3000]").return_fields("model", "type", "price", "description"))
-
diff --git a/docs/examples/bikes_3/example.json b/docs/examples/bikes_3/example.json
deleted file mode 100644
index 4553503..0000000
--- a/docs/examples/bikes_3/example.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "id": "bike_search",
- "file": "bike_search.py"
-}
diff --git a/docs/examples/bikes_4/bike_advanced_search.py b/docs/examples/bikes_4/bike_advanced_search.py
deleted file mode 100644
index 1e33656..0000000
--- a/docs/examples/bikes_4/bike_advanced_search.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-bikes = [{"model": "Ariel", "brand": "Velorim", "price": 2098, "type": "Road bikes", "specs": {"material": "carbon", "weight": 10.9}, "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability."},{"model": "Makemake", "brand": "Breakout", "price": 4551, "type": "Commuter bikes", "specs": {"material": "carbon", "weight": 12.9}, "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "BikeShind", "price": 2637, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 7.3}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability."},{"model": "Tethys", "brand": "Classic wheels", "price": 2018, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 15.7}, "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides."},{"model": "Tethys", "brand": "ScramBikes", "price": 3344, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 14.7}, "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get."},{"model": "Deimos", "brand": "Bold bicycles", "price": 2652, "type": "Commuter bikes", "specs": {"material": "aluminium", "weight": 13.7}, "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "ScramBikes", "price": 2707, "type": "Enduro bikes", "specs": {"material": "full-carbon", "weight": 11.8}, "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost."},{"model": "Mars", "brand": "7th Generation", "price": 2206, "type": "Kids mountain bikes", "specs": {"material": "aluminium", "weight": 8.9}, "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden."},{"model": "Millenium-falcon", "brand": "Breakout", "price": 826, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 9.0}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership."}]
-
-count = 0
-for bike in bikes:
- r.json().set(f"bikes:{count}", "$", bike)
- count += 1
-
-# define the fields for a bike
-bike_schema = [
- TextField("$.model", as_name="model", sortable=True, no_stem=True),
- TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
- NumericField("$.price", as_name="price", sortable=True),
- TagField("$.type", as_name="type"),
- TagField("$.specs.material", as_name="material"),
- NumericField("$.specs.weight", as_name="weight", sortable=True),
- TextField("$.description", as_name="description")
- ]
-
-# define index information
-schema_info = IndexDefinition(
- index_type=IndexType.JSON,
- prefix=["bikes:"])
-
-# create the index
-r.ft("idx:bikes").create_index(bike_schema,definition=schema_info)
-
-# aggregate request to get the number of bikes of each type that are priced between 1000 and 3000
-x = AggregateRequest("@price:[1000 3000]").group_by("@type", reducers.count()).sort_by(Desc("@type"))
-r.ft("idx:bikes").aggregate(x).rows
-
-# aggregate request to get average weight of bikes in each category (type)
-y = AggregateRequest("*").group_by("@type", reducers.avg("@weight").alias("average_bike_weight")).sort_by(Desc("@average_bike_weight"))
-r.ft("idx:bikes").aggregate(y).rows
-
-# aggregate request to get the number of bikes per weight range using the floor() function to create weight groups
-z = AggregateRequest("*").apply(weight="floor(@weight)").group_by("@weight", reducers.count().alias("count")).sort_by("@weight")
-r.ft("idx:bikes").aggregate(z).rows \ No newline at end of file
diff --git a/docs/examples/bikes_4/example.json b/docs/examples/bikes_4/example.json
deleted file mode 100644
index aeedfd1..0000000
--- a/docs/examples/bikes_4/example.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "id": "bike_advanced_search",
- "file": "bike_advanced_search.py"
-}
diff --git a/docs/examples/json_bikes/bike_advanced_search.py b/docs/examples/json_bikes/bike_advanced_search.py
deleted file mode 100644
index 1e33656..0000000
--- a/docs/examples/json_bikes/bike_advanced_search.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-bikes = [{"model": "Ariel", "brand": "Velorim", "price": 2098, "type": "Road bikes", "specs": {"material": "carbon", "weight": 10.9}, "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability."},{"model": "Makemake", "brand": "Breakout", "price": 4551, "type": "Commuter bikes", "specs": {"material": "carbon", "weight": 12.9}, "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "BikeShind", "price": 2637, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 7.3}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability."},{"model": "Tethys", "brand": "Classic wheels", "price": 2018, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 15.7}, "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides."},{"model": "Tethys", "brand": "ScramBikes", "price": 3344, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 14.7}, "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get."},{"model": "Deimos", "brand": "Bold bicycles", "price": 2652, "type": "Commuter bikes", "specs": {"material": "aluminium", "weight": 13.7}, "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "ScramBikes", "price": 2707, "type": "Enduro bikes", "specs": {"material": "full-carbon", "weight": 11.8}, "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost."},{"model": "Mars", "brand": "7th Generation", "price": 2206, "type": "Kids mountain bikes", "specs": {"material": "aluminium", "weight": 8.9}, "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden."},{"model": "Millenium-falcon", "brand": "Breakout", "price": 826, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 9.0}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership."}]
-
-count = 0
-for bike in bikes:
- r.json().set(f"bikes:{count}", "$", bike)
- count += 1
-
-# define the fields for a bike
-bike_schema = [
- TextField("$.model", as_name="model", sortable=True, no_stem=True),
- TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
- NumericField("$.price", as_name="price", sortable=True),
- TagField("$.type", as_name="type"),
- TagField("$.specs.material", as_name="material"),
- NumericField("$.specs.weight", as_name="weight", sortable=True),
- TextField("$.description", as_name="description")
- ]
-
-# define index information
-schema_info = IndexDefinition(
- index_type=IndexType.JSON,
- prefix=["bikes:"])
-
-# create the index
-r.ft("idx:bikes").create_index(bike_schema,definition=schema_info)
-
-# aggregate request to get the number of bikes of each type that are priced between 1000 and 3000
-x = AggregateRequest("@price:[1000 3000]").group_by("@type", reducers.count()).sort_by(Desc("@type"))
-r.ft("idx:bikes").aggregate(x).rows
-
-# aggregate request to get average weight of bikes in each category (type)
-y = AggregateRequest("*").group_by("@type", reducers.avg("@weight").alias("average_bike_weight")).sort_by(Desc("@average_bike_weight"))
-r.ft("idx:bikes").aggregate(y).rows
-
-# aggregate request to get the number of bikes per weight range using the floor() function to create weight groups
-z = AggregateRequest("*").apply(weight="floor(@weight)").group_by("@weight", reducers.count().alias("count")).sort_by("@weight")
-r.ft("idx:bikes").aggregate(z).rows \ No newline at end of file
diff --git a/docs/examples/json_bikes/bike_index.py b/docs/examples/json_bikes/bike_index.py
deleted file mode 100644
index d8945f1..0000000
--- a/docs/examples/json_bikes/bike_index.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-bikes = [{"model": "Ariel", "brand": "Velorim", "price": 2098, "type": "Road bikes", "specs": {"material": "carbon", "weight": 10.9}, "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability."},{"model": "Makemake", "brand": "Breakout", "price": 4551, "type": "Commuter bikes", "specs": {"material": "carbon", "weight": 12.9}, "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "BikeShind", "price": 2637, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 7.3}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability."},{"model": "Tethys", "brand": "Classic wheels", "price": 2018, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 15.7}, "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides."},{"model": "Tethys", "brand": "ScramBikes", "price": 3344, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 14.7}, "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get."},{"model": "Deimos", "brand": "Bold bicycles", "price": 2652, "type": "Commuter bikes", "specs": {"material": "aluminium", "weight": 13.7}, "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "ScramBikes", "price": 2707, "type": "Enduro bikes", "specs": {"material": "full-carbon", "weight": 11.8}, "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost."},{"model": "Mars", "brand": "7th Generation", "price": 2206, "type": "Kids mountain bikes", "specs": {"material": "aluminium", "weight": 8.9}, "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden."},{"model": "Millenium-falcon", "brand": "Breakout", "price": 826, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 9.0}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership."}]
-
-count = 0
-for bike in bikes:
- r.json().set(f"bikes:{count}", "$", bike)
- count += 1
-
-# define the fields for a bike
-bike_schema = [
- TextField("$.model", as_name="model", sortable=True, no_stem=True),
- TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
- NumericField("$.price", as_name="price", sortable=True),
- TagField("$.type", as_name="type"),
- TagField("$.specs.material", as_name="material"),
- NumericField("$.specs.weight", as_name="weight", sortable=True),
- TextField("$.description", as_name="description")
- ]
-
-# define index information
-schema_info = IndexDefinition(
- index_type=IndexType.JSON,
- prefix=["bikes:"])
-
-# create the index
-r.ft("idx:bikes").create_index(bike_schema,definition=schema_info) \ No newline at end of file
diff --git a/docs/examples/json_bikes/bike_search.py b/docs/examples/json_bikes/bike_search.py
deleted file mode 100644
index 1093547..0000000
--- a/docs/examples/json_bikes/bike_search.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-bikes = [{"model": "Ariel", "brand": "Velorim", "price": 2098, "type": "Road bikes", "specs": {"material": "carbon", "weight": 10.9}, "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability."},{"model": "Makemake", "brand": "Breakout", "price": 4551, "type": "Commuter bikes", "specs": {"material": "carbon", "weight": 12.9}, "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "BikeShind", "price": 2637, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 7.3}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability."},{"model": "Tethys", "brand": "Classic wheels", "price": 2018, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 15.7}, "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides."},{"model": "Tethys", "brand": "ScramBikes", "price": 3344, "type": "Kids mountain bikes", "specs": {"material": "carbon", "weight": 14.7}, "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get."},{"model": "Deimos", "brand": "Bold bicycles", "price": 2652, "type": "Commuter bikes", "specs": {"material": "aluminium", "weight": 13.7}, "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price."},{"model": "Iapetus", "brand": "ScramBikes", "price": 2707, "type": "Enduro bikes", "specs": {"material": "full-carbon", "weight": 11.8}, "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost."},{"model": "Mars", "brand": "7th Generation", "price": 2206, "type": "Kids mountain bikes", "specs": {"material": "aluminium", "weight": 8.9}, "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden."},{"model": "Millenium-falcon", "brand": "Breakout", "price": 826, "type": "Mountain bikes", "specs": {"material": "aluminium", "weight": 9.0}, "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership."}]
-
-count = 0
-for bike in bikes:
- r.json().set(f"bikes:{count}", "$", bike)
- count += 1
-
-# define the fields for a bike
-bike_schema = [
- TextField("$.model", as_name="model", sortable=True, no_stem=True),
- TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
- NumericField("$.price", as_name="price", sortable=True),
- TagField("$.type", as_name="type"),
- TagField("$.specs.material", as_name="material"),
- NumericField("$.specs.weight", as_name="weight", sortable=True),
- TextField("$.description", as_name="description")
- ]
-
-# define index information
-schema_info = IndexDefinition(
- index_type=IndexType.JSON,
- prefix=["bikes:"])
-
-# create the index
-r.ft("idx:bikes").create_index(bike_schema,definition=schema_info)
-
-r.ft("idx:bikes").search(Query("@type:{eBikes}"))
-r.ft("idx:bikes").search(Query("@type:{eBikes} @price:[200 1200]").return_fields("model", "type", "price"))
-r.ft("idx:bikes").search(Query("mudguards @type:{Mountain bikes} @price:[1000 3000]").return_fields("model", "type", "price", "description"))
-
diff --git a/docs/examples/json_bikes/bike_setup.py b/docs/examples/json_bikes/bike_setup.py
deleted file mode 100644
index 4aea417..0000000
--- a/docs/examples/json_bikes/bike_setup.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import redis
-import json
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-from redis.commands.search.field import TextField, TagField, NumericField
-from redis.commands.search.query import Query
-from redis.commands.search.aggregation import AggregateRequest, Desc, Asc
-import redis.commands.search.reducers as reducers
-
-# define a Redis connection
-r = redis.Redis(
- host="localhost",
- port=6379,
- db=0,
- decode_responses=True
-)
-
-# a single bike to demonstrate the basics
-bike1 = {
- "model": "Hyperion",
- "brand": "Velorim",
- "price": 844,
- "type": "Enduro bikes",
- "specs": {
- "material": "full-carbon",
- "weight": 8.7
- },
- "description": "This is a mid-travel trail slayer that is a fantastic daily driver or one bike quiver. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you\"re now getting DT Swiss R470 rims with the Formula hubs. Put it all together and you get a bike that helps redefine what can be done for this price."
-}
-
-r.json().set("bikes:1", "$", bike1)
-
-r.json().get("bikes:1", "$.model")
-r.json().get("bikes:1", "$.specs.material")
-
-r.json().set("bikes:1", "$.model", "Hyperion1")
-r.json().get("bikes:1", "$.model") \ No newline at end of file
diff --git a/docs/examples/json_search/example.json b/docs/examples/json_search/example.json
deleted file mode 100644
index 835782a..0000000
--- a/docs/examples/json_search/example.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "id": "json_search",
- "file": "main.py"
-}
diff --git a/docs/examples/json_search/main.py b/docs/examples/json_search/main.py
deleted file mode 100644
index 409592f..0000000
--- a/docs/examples/json_search/main.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# HIDE_START
-import redis
-from redis.commands.json.path import Path
-from redis.commands.search.field import TextField, NumericField, TagField
-from redis.commands.search.indexDefinition import IndexDefinition, IndexType
-# HIDE_END
-
-r = redis.Redis(host='localhost', port=6379)
-user1 = {
- "user":{
- "name": "Paul John",
- "email": "paul.john@example.com",
- "age": 42,
- "city": "London"
- }
-}
-user2 = {
- "user":{
- "name": "Eden Zamir",
- "email": "eden.zamir@example.com",
- "age": 29,
- "city": "Tel Aviv"
- }
-}
-user3 = {
- "user":{
- "name": "Paul Zamir",
- "email": "paul.zamir@example.com",
- "age": 35,
- "city": "Tel Aviv"
- }
-}
-
-r.json().set("user:1", Path.root_path(), user1)
-r.json().set("user:2", Path.root_path(), user2)
-r.json().set("user:3", Path.root_path(), user3)
diff --git a/doctests/README.md b/doctests/README.md
new file mode 100644
index 0000000..f2bfc10
--- /dev/null
+++ b/doctests/README.md
@@ -0,0 +1,31 @@
+# Command examples for redis.io
+
+## How to add an example
+
+Create regular python file in the current folder with meaningful name. It makes sense prefix example files with
+command category (e.g. string, set, list, hash, etc) to make navigation in the folder easier. Files ending in *.py*
+are automatically run by the test suite.
+
+### Special markup
+
+See https://github.com/redis-stack/redis-stack-website#readme for more details.
+
+## How to test examples
+
+Examples are standalone python scripts, committed to the *doctests* directory. These scripts assume that the
+```requirements.txt``` and ```dev_requirements.txt``` from this repository have been installed, as per below.
+
+```bash
+pip install requirements.txt
+pip install dev_requirements.txt
+```
+
+Note - the CI process, runs the basic ```black``` and ```isort``` linters against the examples. Assuming
+the requirements above have been installed you can run ```black yourfile.py``` and ```isort yourfile.py```
+locally to validate the linting, prior to CI.
+
+Just include necessary assertions in the example file and run
+```bash
+sh doctests/run_examples.sh
+```
+to test all examples in the current folder. \ No newline at end of file
diff --git a/doctests/bike_advanced_search.py b/doctests/bike_advanced_search.py
new file mode 100644
index 0000000..01dbfdd
--- /dev/null
+++ b/doctests/bike_advanced_search.py
@@ -0,0 +1,135 @@
+# EXAMPLE: bike_advanced_search
+import json
+
+import redis
+import redis.commands.search.reducers as reducers
+from redis.commands.search.aggregation import AggregateRequest, Asc, Desc
+from redis.commands.search.field import NumericField, TagField, TextField
+from redis.commands.search.indexDefinition import IndexDefinition, IndexType
+from redis.commands.search.query import Query
+
+# define a Redis connection
+r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
+
+bikes = [
+ {
+ "model": "Ariel",
+ "brand": "Velorim",
+ "price": 2098,
+ "type": "Road bikes",
+ "specs": {"material": "carbon", "weight": 10.9},
+ "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability.",
+ },
+ {
+ "model": "Makemake",
+ "brand": "Breakout",
+ "price": 4551,
+ "type": "Commuter bikes",
+ "specs": {"material": "carbon", "weight": 12.9},
+ "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price.",
+ },
+ {
+ "model": "Iapetus",
+ "brand": "BikeShind",
+ "price": 2637,
+ "type": "Mountain bikes",
+ "specs": {"material": "aluminium", "weight": 7.3},
+ "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability.",
+ },
+ {
+ "model": "Tethys",
+ "brand": "Classic wheels",
+ "price": 2018,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "carbon", "weight": 15.7},
+ "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides.",
+ },
+ {
+ "model": "Tethys",
+ "brand": "ScramBikes",
+ "price": 3344,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "carbon", "weight": 14.7},
+ "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get.",
+ },
+ {
+ "model": "Deimos",
+ "brand": "Bold bicycles",
+ "price": 2652,
+ "type": "Commuter bikes",
+ "specs": {"material": "aluminium", "weight": 13.7},
+ "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price.",
+ },
+ {
+ "model": "Iapetus",
+ "brand": "ScramBikes",
+ "price": 2707,
+ "type": "Enduro bikes",
+ "specs": {"material": "full-carbon", "weight": 11.8},
+ "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost.",
+ },
+ {
+ "model": "Mars",
+ "brand": "7th Generation",
+ "price": 2206,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "aluminium", "weight": 8.9},
+ "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden.",
+ },
+ {
+ "model": "Millenium-falcon",
+ "brand": "Breakout",
+ "price": 826,
+ "type": "Mountain bikes",
+ "specs": {"material": "aluminium", "weight": 9.0},
+ "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership.",
+ },
+]
+
+# TUTORIAL_STEP
+count = 0
+for bike in bikes:
+ r.json().set(f"bikes:{count}", "$", bike)
+ count += 1
+
+# define the fields for a bike
+bike_schema = [
+ TextField("$.model", as_name="model", sortable=True, no_stem=True),
+ TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
+ NumericField("$.price", as_name="price", sortable=True),
+ TagField("$.type", as_name="type"),
+ TagField("$.specs.material", as_name="material"),
+ NumericField("$.specs.weight", as_name="weight", sortable=True),
+ TextField("$.description", as_name="description"),
+]
+
+# define index information
+schema_info = IndexDefinition(index_type=IndexType.JSON, prefix=["bikes:"])
+
+# create the index
+r.ft("idx:bikes").create_index(bike_schema, definition=schema_info)
+
+# aggregate request to get the number of bikes of each type that are priced between 1000 and 3000
+x = (
+ AggregateRequest("@price:[1000 3000]")
+ .group_by("@type", reducers.count())
+ .sort_by(Desc("@type"))
+)
+r.ft("idx:bikes").aggregate(x).rows
+
+# aggregate request to get average weight of bikes in each category (type)
+y = (
+ AggregateRequest("*")
+ .group_by("@type", reducers.avg("@weight").alias("average_bike_weight"))
+ .sort_by(Desc("@average_bike_weight"))
+)
+r.ft("idx:bikes").aggregate(y).rows
+
+# aggregate request to get the number of bikes per weight range using the floor() function to create weight groups
+z = (
+ AggregateRequest("*")
+ .apply(weight="floor(@weight)")
+ .group_by("@weight", reducers.count().alias("count"))
+ .sort_by("@weight")
+)
+r.ft("idx:bikes").aggregate(z).rows
diff --git a/doctests/bike_index.py b/doctests/bike_index.py
new file mode 100644
index 0000000..993f342
--- /dev/null
+++ b/doctests/bike_index.py
@@ -0,0 +1,109 @@
+# EXAMPLE: bike_index
+import json
+
+import redis
+import redis.commands.search.reducers as reducers
+from redis.commands.search.aggregation import AggregateRequest, Asc, Desc
+from redis.commands.search.field import NumericField, TagField, TextField
+from redis.commands.search.indexDefinition import IndexDefinition, IndexType
+from redis.commands.search.query import Query
+
+# define a Redis connection
+r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
+
+bikes = [
+ {
+ "model": "Ariel",
+ "brand": "Velorim",
+ "price": 2098,
+ "type": "Road bikes",
+ "specs": {"material": "carbon", "weight": 10.9},
+ "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability.",
+ },
+ {
+ "model": "Makemake",
+ "brand": "Breakout",
+ "price": 4551,
+ "type": "Commuter bikes",
+ "specs": {"material": "carbon", "weight": 12.9},
+ "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price.",
+ },
+ {
+ "model": "Iapetus",
+ "brand": "BikeShind",
+ "price": 2637,
+ "type": "Mountain bikes",
+ "specs": {"material": "aluminium", "weight": 7.3},
+ "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability.",
+ },
+ {
+ "model": "Tethys",
+ "brand": "Classic wheels",
+ "price": 2018,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "carbon", "weight": 15.7},
+ "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides.",
+ },
+ {
+ "model": "Tethys",
+ "brand": "ScramBikes",
+ "price": 3344,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "carbon", "weight": 14.7},
+ "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get.",
+ },
+ {
+ "model": "Deimos",
+ "brand": "Bold bicycles",
+ "price": 2652,
+ "type": "Commuter bikes",
+ "specs": {"material": "aluminium", "weight": 13.7},
+ "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price.",
+ },
+ {
+ "model": "Iapetus",
+ "brand": "ScramBikes",
+ "price": 2707,
+ "type": "Enduro bikes",
+ "specs": {"material": "full-carbon", "weight": 11.8},
+ "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost.",
+ },
+ {
+ "model": "Mars",
+ "brand": "7th Generation",
+ "price": 2206,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "aluminium", "weight": 8.9},
+ "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden.",
+ },
+ {
+ "model": "Millenium-falcon",
+ "brand": "Breakout",
+ "price": 826,
+ "type": "Mountain bikes",
+ "specs": {"material": "aluminium", "weight": 9.0},
+ "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership.",
+ },
+]
+
+count = 0
+for bike in bikes:
+ r.json().set(f"bikes:{count}", "$", bike)
+ count += 1
+
+# define the fields for a bike
+bike_schema = [
+ TextField("$.model", as_name="model", sortable=True, no_stem=True),
+ TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
+ NumericField("$.price", as_name="price", sortable=True),
+ TagField("$.type", as_name="type"),
+ TagField("$.specs.material", as_name="material"),
+ NumericField("$.specs.weight", as_name="weight", sortable=True),
+ TextField("$.description", as_name="description"),
+]
+
+# define index information
+schema_info = IndexDefinition(index_type=IndexType.JSON, prefix=["bikes:"])
+
+# create the index
+r.ft("idx:bikes").create_index(bike_schema, definition=schema_info)
diff --git a/doctests/bike_search.py b/doctests/bike_search.py
new file mode 100644
index 0000000..74a21fe
--- /dev/null
+++ b/doctests/bike_search.py
@@ -0,0 +1,119 @@
+# EXAMPLE: bike_search
+import json
+
+import redis
+import redis.commands.search.reducers as reducers
+from redis.commands.search.aggregation import AggregateRequest, Asc, Desc
+from redis.commands.search.field import NumericField, TagField, TextField
+from redis.commands.search.indexDefinition import IndexDefinition, IndexType
+from redis.commands.search.query import Query
+
+# define a Redis connection
+r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
+
+bikes = [
+ {
+ "model": "Ariel",
+ "brand": "Velorim",
+ "price": 2098,
+ "type": "Road bikes",
+ "specs": {"material": "carbon", "weight": 10.9},
+ "description": "The bike has a lightweight form factor, making it easier for seniors to use. The hydraulic disc brakes provide powerful and modulated braking even in wet conditions, whilst the 3x8 drivetrain offers a huge choice of gears. It's for the rider who wants both efficiency and capability.",
+ },
+ {
+ "model": "Makemake",
+ "brand": "Breakout",
+ "price": 4551,
+ "type": "Commuter bikes",
+ "specs": {"material": "carbon", "weight": 12.9},
+ "description": "The perfect commuter bike for anyone who is constantly rushing around, and prone to forgetting to charge lights, maintain their bike, or not quite getting round to checking weather reports. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. Put it all together and you get a bike that helps redefine what can be done for this price.",
+ },
+ {
+ "model": "Iapetus",
+ "brand": "BikeShind",
+ "price": 2637,
+ "type": "Mountain bikes",
+ "specs": {"material": "aluminium", "weight": 7.3},
+ "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It's for the rider who wants both efficiency and capability.",
+ },
+ {
+ "model": "Tethys",
+ "brand": "Classic wheels",
+ "price": 2018,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "carbon", "weight": 15.7},
+ "description": "Small and powerful, this bike is the best ride for the smallest of tikes. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you're now getting DT Swiss R470 rims with the Formula hubs. That said, we feel this bike is a fantastic option for the rider seeking the versatility that this highly adjustable bike provides.",
+ },
+ {
+ "model": "Tethys",
+ "brand": "ScramBikes",
+ "price": 3344,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "carbon", "weight": 14.7},
+ "description": "Kids want to ride with as little weight as possible. Especially on an incline! With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. If you're after a budget option, this is one of the best bikes you could get.",
+ },
+ {
+ "model": "Deimos",
+ "brand": "Bold bicycles",
+ "price": 2652,
+ "type": "Commuter bikes",
+ "specs": {"material": "aluminium", "weight": 13.7},
+ "description": "This bike is the perfect commuting companion for anyone just looking to get the job done With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. Put it all together and you get a bike that helps redefine what can be done for this price.",
+ },
+ {
+ "model": "Iapetus",
+ "brand": "ScramBikes",
+ "price": 2707,
+ "type": "Enduro bikes",
+ "specs": {"material": "full-carbon", "weight": 11.8},
+ "description": "The new version with 142mm rear, 160mm front travel is longer and slacker than its previous generation, but it's also a bit taller and steeper than much of its competition. With a slick-shifting Claris gears from Shimano's, this is a bike which doesn't break the bank and delivers craved performance. It comes fully assembled (no convoluted instructions!) and includes a sturdy helmet at no cost.",
+ },
+ {
+ "model": "Mars",
+ "brand": "7th Generation",
+ "price": 2206,
+ "type": "Kids mountain bikes",
+ "specs": {"material": "aluminium", "weight": 8.9},
+ "description": "This bike is an entry-level kids mountain bike that is a good choice if your MTB enthusiast is just taking to the trails and wants good suspension and easy gearing, without the cost of some more expensive models. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. All bikes are great in their own way, but this bike will be one of the best you've ridden.",
+ },
+ {
+ "model": "Millenium-falcon",
+ "brand": "Breakout",
+ "price": 826,
+ "type": "Mountain bikes",
+ "specs": {"material": "aluminium", "weight": 9.0},
+ "description": "This bike fills the space between a pure XC race bike, and a trail bike. It is light, with shorter travel (115mm rear and 120mm front), and quick handling. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. This is the bike for the rider who wants trail manners with low fuss ownership.",
+ },
+]
+
+count = 0
+for bike in bikes:
+ r.json().set(f"bikes:{count}", "$", bike)
+ count += 1
+
+# define the fields for a bike
+bike_schema = [
+ TextField("$.model", as_name="model", sortable=True, no_stem=True),
+ TextField("$.brand", as_name="brand", sortable=True, no_stem=True),
+ NumericField("$.price", as_name="price", sortable=True),
+ TagField("$.type", as_name="type"),
+ TagField("$.specs.material", as_name="material"),
+ NumericField("$.specs.weight", as_name="weight", sortable=True),
+ TextField("$.description", as_name="description"),
+]
+
+# define index information
+schema_info = IndexDefinition(index_type=IndexType.JSON, prefix=["bikes:"])
+
+# create the index
+r.ft("idx:bikes").create_index(bike_schema, definition=schema_info)
+
+r.ft("idx:bikes").search(Query("@type:{eBikes}"))
+r.ft("idx:bikes").search(
+ Query("@type:{eBikes} @price:[200 1200]").return_fields("model", "type", "price")
+)
+r.ft("idx:bikes").search(
+ Query("mudguards @type:{Mountain bikes} @price:[1000 3000]").return_fields(
+ "model", "type", "price", "description"
+ )
+)
diff --git a/doctests/bike_setup.py b/doctests/bike_setup.py
new file mode 100644
index 0000000..9be7ad7
--- /dev/null
+++ b/doctests/bike_setup.py
@@ -0,0 +1,30 @@
+# EXAMPLE: bike_setup
+import json
+
+import redis
+import redis.commands.search.reducers as reducers
+from redis.commands.search.aggregation import AggregateRequest, Asc, Desc
+from redis.commands.search.field import NumericField, TagField, TextField
+from redis.commands.search.indexDefinition import IndexDefinition, IndexType
+from redis.commands.search.query import Query
+
+# define a Redis connection
+r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
+
+# a single bike to demonstrate the basics
+bike1 = {
+ "model": "Hyperion",
+ "brand": "Velorim",
+ "price": 844,
+ "type": "Enduro bikes",
+ "specs": {"material": "full-carbon", "weight": 8.7},
+ "description": 'This is a mid-travel trail slayer that is a fantastic daily driver or one bike quiver. At this price point, you get a Shimano 105 hydraulic groupset with a RS510 crank set. The wheels have had a slight upgrade for 2022, so you"re now getting DT Swiss R470 rims with the Formula hubs. Put it all together and you get a bike that helps redefine what can be done for this price.',
+}
+
+r.json().set("bikes:1", "$", bike1)
+
+r.json().get("bikes:1", "$.model")
+r.json().get("bikes:1", "$.specs.material")
+
+r.json().set("bikes:1", "$.model", "Hyperion1")
+r.json().get("bikes:1", "$.model")
diff --git a/doctests/run_examples.sh b/doctests/run_examples.sh
new file mode 100644
index 0000000..5136063
--- /dev/null
+++ b/doctests/run_examples.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+
+basepath=`readlink -f $1`
+if [ $? -ne 0 ]; then
+basepath=`readlink -f $(dirname $0)`
+fi
+echo "No path specified, using ${basepath}"
+
+set -e
+cd ${basepath}
+for i in `ls ${basepath}/*.py`; do
+ redis-cli flushdb
+ python $i
+done
diff --git a/doctests/string_set_get.py b/doctests/string_set_get.py
new file mode 100644
index 0000000..b7801e0
--- /dev/null
+++ b/doctests/string_set_get.py
@@ -0,0 +1,20 @@
+# EXAMPLE: set_and_get
+# HIDE_START
+import redis
+
+r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
+# HIDE_END
+
+res = r.set("foo", "bar")
+print(res)
+# >>> True
+# REMOVE_START
+assert res
+# REMOVE_END
+
+res = r.get("foo")
+print(res)
+# >>> "bar"
+# REMOVE_START
+assert res == "bar"
+# REMOVE_END