diff --git a/docs/img/tutorial/indexes/dictionary001.drawio b/docs/img/tutorial/indexes/dictionary001.drawio
new file mode 100644
index 0000000..659f6b5
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary001.drawio
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary001.svg b/docs/img/tutorial/indexes/dictionary001.svg
new file mode 100644
index 0000000..b543793
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary001.svg
@@ -0,0 +1,57 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary002.drawio b/docs/img/tutorial/indexes/dictionary002.drawio
new file mode 100644
index 0000000..cb1857b
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary002.drawio
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary002.svg b/docs/img/tutorial/indexes/dictionary002.svg
new file mode 100644
index 0000000..677687d
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary002.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary003.drawio b/docs/img/tutorial/indexes/dictionary003.drawio
new file mode 100644
index 0000000..845eb06
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary003.drawio
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary003.svg b/docs/img/tutorial/indexes/dictionary003.svg
new file mode 100644
index 0000000..d667a68
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary003.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary004.drawio b/docs/img/tutorial/indexes/dictionary004.drawio
new file mode 100644
index 0000000..14bbb1e
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary004.drawio
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary004.svg b/docs/img/tutorial/indexes/dictionary004.svg
new file mode 100644
index 0000000..f881d6c
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary004.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary005.drawio b/docs/img/tutorial/indexes/dictionary005.drawio
new file mode 100644
index 0000000..9e339c1
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary005.drawio
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary005.svg b/docs/img/tutorial/indexes/dictionary005.svg
new file mode 100644
index 0000000..9d37624
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary005.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary006.drawio b/docs/img/tutorial/indexes/dictionary006.drawio
new file mode 100644
index 0000000..3c669d3
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary006.drawio
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary006.svg b/docs/img/tutorial/indexes/dictionary006.svg
new file mode 100644
index 0000000..30be80e
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary006.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary007.drawio b/docs/img/tutorial/indexes/dictionary007.drawio
new file mode 100644
index 0000000..89b32ca
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary007.drawio
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary007.svg b/docs/img/tutorial/indexes/dictionary007.svg
new file mode 100644
index 0000000..79e7950
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary007.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary008.drawio b/docs/img/tutorial/indexes/dictionary008.drawio
new file mode 100644
index 0000000..ac08ad0
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary008.drawio
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/dictionary008.svg b/docs/img/tutorial/indexes/dictionary008.svg
new file mode 100644
index 0000000..013a4d6
--- /dev/null
+++ b/docs/img/tutorial/indexes/dictionary008.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/techbook001.drawio b/docs/img/tutorial/indexes/techbook001.drawio
new file mode 100644
index 0000000..de1c256
--- /dev/null
+++ b/docs/img/tutorial/indexes/techbook001.drawio
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/img/tutorial/indexes/techbook001.svg b/docs/img/tutorial/indexes/techbook001.svg
new file mode 100644
index 0000000..8b0c09d
--- /dev/null
+++ b/docs/img/tutorial/indexes/techbook001.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/tutorial/connect/create-connected-tables.md b/docs/tutorial/connect/create-connected-tables.md
index 90301ee..452c904 100644
--- a/docs/tutorial/connect/create-connected-tables.md
+++ b/docs/tutorial/connect/create-connected-tables.md
@@ -78,6 +78,7 @@ The `Team` model will be in a table automatically named `"team"`, and it will ha
* `id`, the primary key, automatically generated by the database
* `name`, the name of the team
+ * We also tell **SQLModel** to create an index for this column
* `headquarters`, the headquarters of the team
And finally we mark it as a table in the config.
diff --git a/docs/tutorial/fastapi/multiple-models.md b/docs/tutorial/fastapi/multiple-models.md
index 5cac6dd..d313874 100644
--- a/docs/tutorial/fastapi/multiple-models.md
+++ b/docs/tutorial/fastapi/multiple-models.md
@@ -305,6 +305,31 @@ And of course, all these fields will be in the columns for the resulting `hero`
And those inherited fields will also be in the **autocompletion** and **inline errors** in editors, etc.
+### Columns and Inheritance with Multiple Models
+
+Notice that the parent model `HeroBase` is not a **table model**, but still, we can declare `name` and `age` using `Field(index=True)`.
+
+```Python hl_lines="4 6 9"
+# Code above omitted 👆
+
+{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py[ln:7-14]!}
+
+# Code below omitted 👇
+```
+
+
+👀 Full file preview
+
+```Python
+{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
+```
+
+
+
+This won't affect this parent **data model** `HeroBase`.
+
+But once the child model `Hero` (the actual **table model**) inherits those fields, it will use those field configurations to create the indexes when creating the tables in the database.
+
### The `HeroCreate` **Data Model**
Now let's see the `HeroCreate` model that will be used to define the data that we want to receive in the API when creating a new hero.
diff --git a/docs/tutorial/indexes.md b/docs/tutorial/indexes.md
new file mode 100644
index 0000000..6513d7d
--- /dev/null
+++ b/docs/tutorial/indexes.md
@@ -0,0 +1,406 @@
+# Indexes - Optimize Queries
+
+We just saw how to get some data `WHERE` a **condition** is true. For example, where the hero **name is "Deadpond"**.
+
+If we just create the tables and the data as we have been doing, when we `SELECT` some data using `WHERE`, the database would have to **scan** through **each one of the records** to find the ones that **match**. This is not a problem with 3 heroes as in these examples.
+
+But imagine that your database has **thousands** or **millions** of **records**, if every time you want to find the heroes with the name "Deadpond" it has to scan through **all** of the records to find all the possible matches, then that becomes problematic, as it would be too slow.
+
+I'll show you how to handle it with a database **index**.
+
+The change in the code is **extremely small**, but it's useful to understand what's happening behind the scenes, so I'll show you **how it all works** and what it means.
+
+---
+
+If you already executed the previous examples and have a database with data, **remove the database file** before running each example, that way you won't have duplicate data and you will be able to get the same results.
+
+## No Time to Explain
+
+Are you already a **SQL expert** and don't have time for all my explanations?
+
+Fine, in that case, you can **sneak peek** the final code to create indexes here.
+
+
+👀 Full file preview
+
+```Python hl_lines="8 10"
+{!./docs_src/tutorial/indexes/tutorial002.py!}
+```
+
+
+
+..but if you are not an expert, **continue reading**, this will probably be useful. 🤓
+
+## What is an Index
+
+In general, an **index** is just something we can have to help us **find things faster**. It normally works by having things in **order**. Let's think about some real-life examples before even thinking about databases and code.
+
+### An Index and a Dictionary
+
+Imagine a **dictionary**, a book with definitions of words. 📔 ...not a Python `dict`. 😅
+
+Let's say that you want to **find a word**, for example the word "**database**". You take the dictionary, and open it somewhere, for example in the middle. Maybe you see some definitions of words that start with `m`, like `manual`, so you conclude that you are in the letter `m` in the dictionary.
+
+
+
+You know that in the alphabet, the letter `d` for `database` comes **before** the letter `m` for `manual`.
+
+
+
+So, you know you have to search in the dictionary **before** the point you currently are. You still don't know where the word `database` is, because you don't know exactly where the letter `d` is in the dictionary, but you know that **it is not after** that point, you can now **discard the right half** of the dictionary in your search.
+
+
+
+Next, you **open the dictionary again**, but only taking into account the **half of the dictionary** that can contain the word you want, the **left part of the dictionary**. You open it in the middle of that left part and now you arrive maybe at the letter `f`.
+
+
+
+You know that `d` from `database` comes before `f`. So it has to be **before** that. But now you know that `database` **is not after** that point, and you can discard the dictionary from that point onward.
+
+
+
+Now you have a **small section of dictionary** to search (only a **quarter** of dictionary can have your word). You take that **quarter** of the pages at the start of the dictionary that can contain your word, and open it in the middle of that section. Maybe you arrive at the letter `c`.
+
+
+
+You know the word `database` has to be **after** that and **not before** that point, so you can discard the left part of that block of pages.
+
+
+
+You repeat this process **a few more times**, and you finally arrive at the letter `d`, you continue with the same process in that section for the letter `d` and you finally **find the word** `database`. 🎉
+
+
+
+You had to open the dictionary a few times, maybe **5 or 10**. That's actually **very little work** compared to what it could have been.
+
+!!! note "Technical Details"
+ Do you like **fancy words**? Cool! Programmers tend to like fancy words. 😅
+
+ That algorithm I showed you above is called **Binary Search**.
+
+ It's called like that because you **search** something by splitting the dictionary (or any ordered list of things) in **two** ("binary" means "two") parts. And you do that process multiple times until you find what you want.
+
+### An Index and a Novel
+
+Let's now imagine you are reading a **novel book**. And someone told you that at some point, they mention a **database**, and you want to find that chapter.
+
+How do you find the word "*database*" there? You might have to read **the entire book** to find where the word "*database*" is located in the book. So, instead of opening the book 5 or 10 times, you would have to open each of the **500 pages** and read them one by one until you find the word. You might enjoy the book, though. 😅
+
+But if we are only interested in **quickly finding information** (as when working with SQL databases), then reading each of the 500 pages is **too inefficient** when there could be an option to open the book in 5 or 10 places and find what you're looking for.
+
+### A Technical Book with an Index
+
+Now let's imagine you are reading a technical book. For example, with several topics about programming. And there's a couple of sections where it talks about a **database**.
+
+This book might have a **book index**: a section in the book that has some **names of topics covered** and the **page numbers** in the book where you can read about them. And the topic names are **sorted** in alphabetic order, pretty much like a dictionary (a book with words, as in the previous example).
+
+In this case, you can open that book in the end (or in the beginning) to find the **book index** section, it would have only a few pages. And then, you can do the same process as with the **dictionary** example above.
+
+Open the index, and after **5 or 10 steps**, quickly find the topic "**database**" with the page numbers where that is covered, for example "page 253 in Chapter 5". Now you used the dictionary technique to find the **topic**, and that topic gave you a **page number**.
+
+Now you know that you need to find "**page 253**". But by looking at the closed book you still don't know where that page is, so you have to **find that page**. To find it, you can do the same process again, but this time, instead of searching for a **topic** in the **index**, you are searching for a **page number** in the **entire book**. And after **5 or 10 more steps**, you find the page 253 in Chapter 5.
+
+
+
+After this, even though this book is not a dictionary and has some particular content, you were able to **find the section** in the book that talks about a "**database**" in a **few steps** (say 10 or 20, instead of reading all the 500 pages).
+
+The main point is that the index is **sorted**, so we can use the same process we used for the **dictionary** to find the topic. And then that gives us a page number, and the **page numbers are also sorted**! 😅
+
+When we have a list of sorted things we can apply the same technique, and that's the whole trick here, we use the same technique first for the **topics** in the index and then for the **page numbers** to find the actual chapter.
+
+Such efficiency! 😎
+
+## What are Database Indexes
+
+**Database indexes** are very similar to **book indexes**.
+
+Database indexes store some info, some keys, in a way that makes it **easy and fast to find** (for example sorted), and then for each key they **point to some data somewhere else** in the database.
+
+Let's see a more clear example. Let's say you have this table in a database:
+
+
+
+
id
name
secret_name
age
+
+
+
1
Deadpond
Dive Wilson
null
+
+
+
2
Spider-Boy
Pedro Parqueador
null
+
+
+
3
Rusty-Man
Tommy Sharp
48
+
+
+
+And let's imagine you have **many more rows**, many more heroes. Probably **thousands**.
+
+If you tell the SQL database to get you a hero by a specific name, for example `Spider-Boy` (by using the `name` in the `WHERE` part of the SQL query), the database will have to **scan** all the heroes, checking **one by one** to find all the ones with a name of `Spider-Boy`.
+
+In this case, there's only one, but there's nothing limiting the database from having **more records with the same name**. And because of that, the database would **continue searching** and checking each one of the records, which would be very slow.
+
+But now let's say that the database has an index for the column `name`. The index could look something like this, we could imagine that the index is like an additional special table that the database manages automatically:
+
+
+
+
name
id
+
+
+
Deadpond
1
+
+
+
Rusty-Man
3
+
+
+
Spider-Boy
2
+
+
+
+It would have each `name` field from the `hero` table **in order**. It would not be sorted by `id`, but by `name` (in alphabetical order, as the `name` is a string). So, first it would have `Deadpond`, then `Rusty-Man`, and last `Spider-Boy`. It would also include the `id` of each hero. Remember that this could have **thousands** of heroes.
+
+Then the database would be able to use more or less the same ideas in the examples above with the **dictionary** and the **book index**.
+
+It could start somewhere (for example, in the middle of the index). It could arrive at some hero there in the middle, like `Rusty-Man`. And because the **index** has the `name` fields in order, the database would know that it can **discard all the previous index rows** and **only search** in the following index rows.
+
+
+
+
name
id
+
+
+
Deadpond
1
+
+
+
Rusty-Man
3
+
+
+
Spider-Boy
2
+
+
+
+And that way, as with the example with the dictionary above, **instead of reading thousands of heroes**, the database would be able to do a few steps, say **5 or 10 steps**, and arrive at the row of the index that has `Spider-Boy`, even if the table (and index) has thousands of rows:
+
+
+
+
name
id
+
+
+
Deadpond
1
+
+
+
Rusty-Man
3
+
+
+
✨ Spider-Boy ✨
2
+
+
+
+Then by looking at **this index row**, it would know that the `id` for `Spider-Boy` in the `hero` table is `2`.
+
+So then it could **search that `id`** in the `hero` table using more or less the **same technique**.
+
+That way, in the end, instead of reading thousands of records, the database only had to do **a few steps** to find the hero we wanted.
+
+## Updating the Index
+
+As you can imagine, for all this to work, the index would need to be **up to date** with the data in the database.
+
+If you had to update it **manually** in code, it would be very cumbersome and **error-prone**, as it would be easy to end up in a state where the index is not up to date and points to incorrect data. 😱
+
+Here's the good news: when you create an index in a **SQL Database**, the database takes care of **updating** it **automatically** whenever it's necessary. 😎🎉
+
+If you **add new records** to the `hero` table, the database will **automatically** update the index. It will do the **same process** of **finding** the right place to put the new index data (those **5 or 10 steps** described above), and then it will save the new index information there. The same would happen when you **update** or **delete** data.
+
+Defining and creating an index is very **easy** with SQL databases. And then **using it** is even easier... it's transparent. The database will figure out which index to use automatically, the SQL queries don't even change.
+
+So, in SQL databases **indexes are great**! And are super **easy to use**. Why not just have indexes for everything? .....Because indexes also have a "**cost**" in computation and storage (disk space).
+
+## Index Cost
+
+There's a **cost** associated with **indexes**. 💰
+
+When you don't have an index and add a **new row** to the table `hero`, the database has to perform **1 operation** to add the new hero row at the end of the table.
+
+But if you have an **index** for the **hero names**, now the database has to perform the same **1 operation** to add that row **plus** some extra **5 or 10 operations** in the index, to find the right spot for the name, to then add that **index record** there.
+
+And if you have an index for the `name`, one for the `age`, and one for the `secret_name`, now the database has to perform the same **1 operation** to add that row **plus** some extra **5 or 10 operations** in the index **times 3**, for each of the indexes. This means that now adding one row takes something like **31 operations**.
+
+This also means that you are **exchanging** the time it takes to **read** data for the time it takes to **write** data plus some extra **space** in the database.
+
+If you have queries that get data out of the database comparing each one of those fields (for example using `WHERE`), then it makes total sense to have indexes for each one of them. Because **31 operations** while creating or updating data (plus the space of the index) is much, much better than the possible **500 or 1000 operations** to read all the rows to be able to compare them using each field.
+
+But if you **never** have queries that find records by the `secret_name` (you never use `secret_name` in the `WHERE` part) it probably doesn't make sense to have an index for the `secret_name` field/column, as that will increase the computational and space **cost** of writing and updating the database.
+
+## Create an Index with SQL
+
+Phew, that was a lot of theory and explanations. 😅
+
+The most important thing about indexes is **understanding** them, how, and when to use them.
+
+Let's now see the **SQL** syntax to create an **index**. It is very simple:
+
+```SQL hl_lines="3"
+CREATE INDEX ix_hero_name
+ON hero (name)
+```
+
+This means, more or less:
+
+> Hey SQL database 👋, please `CREATE` an `INDEX` for me.
+>
+> I want the name of the index to be `ix_hero_name`.
+>
+> This index should be `ON` the table `hero`, it refers to that table.
+>
+> The column I want you to use for it is `name`.
+
+## Declare Indexes with SQLModel
+
+And now let's see how to define indexes in **SQLModel**.
+
+The change in code is underwhelming, it's very simple. 😆
+
+Here's the `Hero` model we had before:
+
+```Python hl_lines="8"
+{!./docs_src/tutorial/where/tutorial001.py[ln:1-10]!}
+
+# Code below omitted 👇
+```
+
+
+👀 Full file preview
+
+```Python
+{!./docs_src/tutorial/where/tutorial001.py!}
+```
+
+
+
+Let's now update it to tell **SQLModel** to create an index for the `name` field when creating the table:
+
+```Python hl_lines="8"
+{!./docs_src/tutorial/indexes/tutorial001.py[ln:1-10]!}
+
+# Code below omitted 👇
+```
+
+
+👀 Full file preview
+
+```Python
+{!./docs_src/tutorial/indexes/tutorial001.py!}
+```
+
+
+
+We use the same `Field()` again as we did before, and set `index=True`. That's it! 🚀
+
+Notice that we didn't set an argument of `default=None` or anything similar. This means that **SQLModel** (thanks to Pydantic) will keep it as a **required** field.
+
+!!! info
+ SQLModel (actually SQLAlchemy) will **automatically generate the index name** for you.
+
+ In this case the generated name would be `ix_hero_name`.
+
+## Query Data
+
+Now, to query the data using the field `name` and the new index we don't have to do anything special or different in the code, it's just **the same code**.
+
+The SQL database will figure it out **automatically**. ✨
+
+This is great because it means that indexes are very **simple to use**. But it might also feel counterintuitive at first, as you are **not doing anything** explicitly in the code to make it obvious that the index is useful, it all happens in the database behind the scenes.
+
+```Python hl_lines="5"
+# Code above omitted 👆
+
+{!./docs_src/tutorial/indexes/tutorial001.py[ln:36-41]!}
+
+# Code below omitted 👇
+```
+
+
+👀 Full file preview
+
+```Python
+{!./docs_src/tutorial/indexes/tutorial001.py!}
+```
+
+
+
+This is exactly the same code as we had before, but now the database will **use the index** underneath.
+
+## Run the Program
+
+If you run the program now, you will see an output like this:
+
+
+
+```console
+$ python app.py
+
+// Some boilerplate output omitted 😉
+
+// Create the table
+CREATE TABLE hero (
+ id INTEGER,
+ name VARCHAR NOT NULL,
+ secret_name VARCHAR NOT NULL,
+ age INTEGER,
+ PRIMARY KEY (id)
+)
+
+// Create the index 🤓🎉
+CREATE INDEX ix_hero_name ON hero (name)
+
+// The SELECT with WHERE looks the same
+INFO Engine SELECT hero.id, hero.name, hero.secret_name, hero.age
+FROM hero
+WHERE hero.name = ?
+INFO Engine [no key 0.00014s] ('Deadpond',)
+
+// The resulting hero
+secret_name='Dive Wilson' age=None id=1 name='Deadpond'
+```
+
+
+
+## More Indexes
+
+We are going to query the `hero` table doing comparisons on the `age` field too, so we should **define an index** for that one as well:
+
+```Python hl_lines="10"
+{!./docs_src/tutorial/indexes/tutorial002.py[ln:1-10]!}
+
+# Code below omitted 👇
+```
+
+
+👀 Full file preview
+
+```Python
+{!./docs_src/tutorial/indexes/tutorial002.py!}
+```
+
+
+
+In this case, we want the default value of `age` to continue being `None`, so we set `default=None` when using `Field()`.
+
+Now when we use **SQLModel** to create the database and tables, it will also create the **indexes** for these two columns in the `hero` table.
+
+So, when we query the database for the `hero` table and use those **two columns** to define what data we get, the database will be able to **use those indexes** to improve the **reading performance**. 🚀
+
+## Primary Key and Indexes
+
+You probably noticed that we didn't set `index=True` for the `id` field.
+
+Because the `id` is already the **primary key**, the database will automatically create an internal **index** for it.
+
+The database always creates an internal index for **primary keys** automatically, as those are the primary way to organize, store, and retrieve data. 🤓
+
+But if you want to be **frequently querying** the SQL database for any **other field** (e.g. using any other field in the `WHERE` section), you will probably want to have at least an **index** for that.
+
+## Recap
+
+**Indexes** are very important to improve **reading performance** and speed when querying the database. 🏎
+
+Creating and using them is very **simple** and easy. The most important part is to understand **how** they work, **when** to create them, and for **which columns**.
diff --git a/docs/tutorial/one.md b/docs/tutorial/one.md
index 901199b..3b60653 100644
--- a/docs/tutorial/one.md
+++ b/docs/tutorial/one.md
@@ -18,7 +18,7 @@ We'll continue with the same examples we have been using in the previous chapter
👀 Full file preview
```Python
-{!./docs_src/tutorial/where/tutorial006.py!}
+{!./docs_src/tutorial/indexes/tutorial002.py!}
```
@@ -32,7 +32,7 @@ We have been iterating over the rows in a `result` object like:
```Python hl_lines="7-8"
# Code above omitted 👆
-{!./docs_src/tutorial/where/tutorial006.py[ln:44-49]!}
+{!./docs_src/tutorial/indexes/tutorial002.py[ln:44-49]!}
# Code below omitted 👇
```
@@ -41,7 +41,7 @@ We have been iterating over the rows in a `result` object like:
👀 Full file preview
```Python
-{!./docs_src/tutorial/where/tutorial006.py!}
+{!./docs_src/tutorial/indexes/tutorial002.py!}
```
diff --git a/docs/tutorial/update.md b/docs/tutorial/update.md
index 420616d..b3099f5 100644
--- a/docs/tutorial/update.md
+++ b/docs/tutorial/update.md
@@ -10,7 +10,7 @@ As before, we'll continue from where we left off with the previous code.
👀 Full file preview
```Python
-{!./docs_src/tutorial/where/tutorial006.py!}
+{!./docs_src/tutorial/indexes/tutorial002.py!}
```
diff --git a/docs/tutorial/where.md b/docs/tutorial/where.md
index fd80712..45e909c 100644
--- a/docs/tutorial/where.md
+++ b/docs/tutorial/where.md
@@ -233,7 +233,7 @@ The object returned by `select(Hero)` is a special type of object with some meth
One of those methods is `.where()` used to (unsurprisingly) add a `WHERE` to the SQL statement in that **select** object.
-There are other methods that will will explore later. 💡
+There are other methods that we will explore later. 💡
Most of these methods return the same object again after modifying it.
@@ -698,7 +698,7 @@ age=35 id=5 name='Black Lion' secret_name='Trevor Challa'
Here's a good moment to see that being able to use these pure Python expressions instead of keyword arguments can help a lot. ✨
-We can use the same standard Python comparison operators like `.
+We can use the same standard Python comparison operators like `<`, `<=`, `>`, `>=`, `==`, etc.
## Multiple `.where()`
@@ -933,3 +933,7 @@ And with that the editor knows this code is actually fine, because this is a spe
## Recap
You can use `.where()` with powerful expressions using **SQLModel** columns (the special class attributes) to filter the rows that you want. 🚀
+
+Up to now, the database would have been **looking through each one of the records** (rows) to find the ones that match what you want. If you have thousands or millions of records, this could be very **slow**. 😱
+
+In the next section I'll tell you how to add **indexes** to the database, this is what will make the queries **very efficient**. 😎
diff --git a/docs_src/advanced/decimal/tutorial001.py b/docs_src/advanced/decimal/tutorial001.py
index 1b16770..b803119 100644
--- a/docs_src/advanced/decimal/tutorial001.py
+++ b/docs_src/advanced/decimal/tutorial001.py
@@ -6,9 +6,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
money: condecimal(max_digits=5, decimal_places=3) = Field(default=0)
diff --git a/docs_src/tutorial/code_structure/tutorial001/models.py b/docs_src/tutorial/code_structure/tutorial001/models.py
index 9bd1fa9..8e2647b 100644
--- a/docs_src/tutorial/code_structure/tutorial001/models.py
+++ b/docs_src/tutorial/code_structure/tutorial001/models.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, SQLModel
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
@@ -13,9 +13,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/code_structure/tutorial002/hero_model.py b/docs_src/tutorial/code_structure/tutorial002/hero_model.py
index 84fc7f2..06dd9c6 100644
--- a/docs_src/tutorial/code_structure/tutorial002/hero_model.py
+++ b/docs_src/tutorial/code_structure/tutorial002/hero_model.py
@@ -8,9 +8,9 @@ if TYPE_CHECKING:
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional["Team"] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/code_structure/tutorial002/team_model.py b/docs_src/tutorial/code_structure/tutorial002/team_model.py
index 54974a0..c8a008b 100644
--- a/docs_src/tutorial/code_structure/tutorial002/team_model.py
+++ b/docs_src/tutorial/code_structure/tutorial002/team_model.py
@@ -8,7 +8,7 @@ if TYPE_CHECKING:
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
diff --git a/docs_src/tutorial/connect/create_tables/tutorial001.py b/docs_src/tutorial/connect/create_tables/tutorial001.py
index 86dcc9a..ef24ec7 100644
--- a/docs_src/tutorial/connect/create_tables/tutorial001.py
+++ b/docs_src/tutorial/connect/create_tables/tutorial001.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, SQLModel, create_engine
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/delete/tutorial001.py b/docs_src/tutorial/connect/delete/tutorial001.py
index 57bbd0e..eeb376a 100644
--- a/docs_src/tutorial/connect/delete/tutorial001.py
+++ b/docs_src/tutorial/connect/delete/tutorial001.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/insert/tutorial001.py b/docs_src/tutorial/connect/insert/tutorial001.py
index d64d37f..dc3661d 100644
--- a/docs_src/tutorial/connect/insert/tutorial001.py
+++ b/docs_src/tutorial/connect/insert/tutorial001.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/select/tutorial001.py b/docs_src/tutorial/connect/select/tutorial001.py
index 18c4f40..d4cdf41 100644
--- a/docs_src/tutorial/connect/select/tutorial001.py
+++ b/docs_src/tutorial/connect/select/tutorial001.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/select/tutorial002.py b/docs_src/tutorial/connect/select/tutorial002.py
index f7df277..59edbf7 100644
--- a/docs_src/tutorial/connect/select/tutorial002.py
+++ b/docs_src/tutorial/connect/select/tutorial002.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/select/tutorial003.py b/docs_src/tutorial/connect/select/tutorial003.py
index 110cace..fb5b8aa 100644
--- a/docs_src/tutorial/connect/select/tutorial003.py
+++ b/docs_src/tutorial/connect/select/tutorial003.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/select/tutorial004.py b/docs_src/tutorial/connect/select/tutorial004.py
index 87e739a..d1d260b 100644
--- a/docs_src/tutorial/connect/select/tutorial004.py
+++ b/docs_src/tutorial/connect/select/tutorial004.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/select/tutorial005.py b/docs_src/tutorial/connect/select/tutorial005.py
index 0e696d0..a61ef8a 100644
--- a/docs_src/tutorial/connect/select/tutorial005.py
+++ b/docs_src/tutorial/connect/select/tutorial005.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/connect/update/tutorial001.py b/docs_src/tutorial/connect/update/tutorial001.py
index 3c9726f..0080340 100644
--- a/docs_src/tutorial/connect/update/tutorial001.py
+++ b/docs_src/tutorial/connect/update/tutorial001.py
@@ -5,15 +5,15 @@ from sqlmodel import Field, Session, SQLModel, create_engine
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/delete/tutorial001.py b/docs_src/tutorial/delete/tutorial001.py
index 0f7c056..7c911df 100644
--- a/docs_src/tutorial/delete/tutorial001.py
+++ b/docs_src/tutorial/delete/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/delete/tutorial002.py b/docs_src/tutorial/delete/tutorial002.py
index 1f26711..202d63b 100644
--- a/docs_src/tutorial/delete/tutorial002.py
+++ b/docs_src/tutorial/delete/tutorial002.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/main.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/main.py
index 02f5ab8..88b8fbb 100644
--- a/docs_src/tutorial/fastapi/app_testing/tutorial001/main.py
+++ b/docs_src/tutorial/fastapi/app_testing/tutorial001/main.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
diff --git a/docs_src/tutorial/fastapi/delete/tutorial001.py b/docs_src/tutorial/fastapi/delete/tutorial001.py
index 19ab2bb..3c15efb 100644
--- a/docs_src/tutorial/fastapi/delete/tutorial001.py
+++ b/docs_src/tutorial/fastapi/delete/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
diff --git a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py b/docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py
index 9bdf604..aef2133 100644
--- a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py
+++ b/docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial001.py b/docs_src/tutorial/fastapi/multiple_models/tutorial001.py
index c46448b..df20123 100644
--- a/docs_src/tutorial/fastapi/multiple_models/tutorial001.py
+++ b/docs_src/tutorial/fastapi/multiple_models/tutorial001.py
@@ -6,9 +6,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class HeroCreate(SQLModel):
diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial002.py b/docs_src/tutorial/fastapi/multiple_models/tutorial002.py
index 537e896..392c2c5 100644
--- a/docs_src/tutorial/fastapi/multiple_models/tutorial002.py
+++ b/docs_src/tutorial/fastapi/multiple_models/tutorial002.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
diff --git a/docs_src/tutorial/fastapi/read_one/tutorial001.py b/docs_src/tutorial/fastapi/read_one/tutorial001.py
index bc83db5..4d66e47 100644
--- a/docs_src/tutorial/fastapi/read_one/tutorial001.py
+++ b/docs_src/tutorial/fastapi/read_one/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
diff --git a/docs_src/tutorial/fastapi/relationships/tutorial001.py b/docs_src/tutorial/fastapi/relationships/tutorial001.py
index da21e46..97220b9 100644
--- a/docs_src/tutorial/fastapi/relationships/tutorial001.py
+++ b/docs_src/tutorial/fastapi/relationships/tutorial001.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, sele
class TeamBase(SQLModel):
- name: str
+ name: str = Field(index=True)
headquarters: str
@@ -30,9 +30,9 @@ class TeamUpdate(SQLModel):
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/fastapi/response_model/tutorial001.py b/docs_src/tutorial/fastapi/response_model/tutorial001.py
index 5f7a190..57d8738 100644
--- a/docs_src/tutorial/fastapi/response_model/tutorial001.py
+++ b/docs_src/tutorial/fastapi/response_model/tutorial001.py
@@ -6,9 +6,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py b/docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py
index 02f5ab8..88b8fbb 100644
--- a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py
+++ b/docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
diff --git a/docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py b/docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py
index 715836c..41eaa62 100644
--- a/docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py
+++ b/docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py
@@ -6,9 +6,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/fastapi/teams/tutorial001.py b/docs_src/tutorial/fastapi/teams/tutorial001.py
index dc3e093..e8f88b8 100644
--- a/docs_src/tutorial/fastapi/teams/tutorial001.py
+++ b/docs_src/tutorial/fastapi/teams/tutorial001.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, sele
class TeamBase(SQLModel):
- name: str
+ name: str = Field(index=True)
headquarters: str
@@ -30,9 +30,9 @@ class TeamUpdate(SQLModel):
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
diff --git a/docs_src/tutorial/fastapi/update/tutorial001.py b/docs_src/tutorial/fastapi/update/tutorial001.py
index 9309d62..3555487 100644
--- a/docs_src/tutorial/fastapi/update/tutorial001.py
+++ b/docs_src/tutorial/fastapi/update/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class HeroBase(SQLModel):
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
diff --git a/docs_src/tutorial/indexes/__init__.py b/docs_src/tutorial/indexes/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/docs_src/tutorial/indexes/tutorial001.py b/docs_src/tutorial/indexes/tutorial001.py
new file mode 100644
index 0000000..539220c
--- /dev/null
+++ b/docs_src/tutorial/indexes/tutorial001.py
@@ -0,0 +1,51 @@
+from typing import Optional
+
+from sqlmodel import Field, Session, SQLModel, create_engine, select
+
+
+class Hero(SQLModel, table=True):
+ id: Optional[int] = Field(default=None, primary_key=True)
+ name: str = Field(index=True)
+ secret_name: str
+ age: Optional[int] = Field(default=None, index=True)
+
+
+sqlite_file_name = "database.db"
+sqlite_url = f"sqlite:///{sqlite_file_name}"
+
+engine = create_engine(sqlite_url, echo=True)
+
+
+def create_db_and_tables():
+ SQLModel.metadata.create_all(engine)
+
+
+def create_heroes():
+ hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
+ hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
+ hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
+
+ with Session(engine) as session:
+ session.add(hero_1)
+ session.add(hero_2)
+ session.add(hero_3)
+
+ session.commit()
+
+
+def select_heroes():
+ with Session(engine) as session:
+ statement = select(Hero).where(Hero.name == "Deadpond")
+ results = session.exec(statement)
+ for hero in results:
+ print(hero)
+
+
+def main():
+ create_db_and_tables()
+ create_heroes()
+ select_heroes()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/docs_src/tutorial/indexes/tutorial002.py b/docs_src/tutorial/indexes/tutorial002.py
new file mode 100644
index 0000000..ebc8d64
--- /dev/null
+++ b/docs_src/tutorial/indexes/tutorial002.py
@@ -0,0 +1,59 @@
+from typing import Optional
+
+from sqlmodel import Field, Session, SQLModel, create_engine, select
+
+
+class Hero(SQLModel, table=True):
+ id: Optional[int] = Field(default=None, primary_key=True)
+ name: str = Field(index=True)
+ secret_name: str
+ age: Optional[int] = Field(default=None, index=True)
+
+
+sqlite_file_name = "database.db"
+sqlite_url = f"sqlite:///{sqlite_file_name}"
+
+engine = create_engine(sqlite_url, echo=True)
+
+
+def create_db_and_tables():
+ SQLModel.metadata.create_all(engine)
+
+
+def create_heroes():
+ hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
+ hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
+ hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
+ hero_4 = Hero(name="Tarantula", secret_name="Natalia Roman-on", age=32)
+ hero_5 = Hero(name="Black Lion", secret_name="Trevor Challa", age=35)
+ hero_6 = Hero(name="Dr. Weird", secret_name="Steve Weird", age=36)
+ hero_7 = Hero(name="Captain North America", secret_name="Esteban Rogelios", age=93)
+
+ with Session(engine) as session:
+ session.add(hero_1)
+ session.add(hero_2)
+ session.add(hero_3)
+ session.add(hero_4)
+ session.add(hero_5)
+ session.add(hero_6)
+ session.add(hero_7)
+
+ session.commit()
+
+
+def select_heroes():
+ with Session(engine) as session:
+ statement = select(Hero).where(Hero.age <= 35)
+ results = session.exec(statement)
+ for hero in results:
+ print(hero)
+
+
+def main():
+ create_db_and_tables()
+ create_heroes()
+ select_heroes()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/docs_src/tutorial/many_to_many/tutorial001.py b/docs_src/tutorial/many_to_many/tutorial001.py
index aee77af..bb4e9d0 100644
--- a/docs_src/tutorial/many_to_many/tutorial001.py
+++ b/docs_src/tutorial/many_to_many/tutorial001.py
@@ -14,7 +14,7 @@ class HeroTeamLink(SQLModel, table=True):
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="teams", link_model=HeroTeamLink)
@@ -22,9 +22,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
teams: List[Team] = Relationship(back_populates="heroes", link_model=HeroTeamLink)
diff --git a/docs_src/tutorial/many_to_many/tutorial002.py b/docs_src/tutorial/many_to_many/tutorial002.py
index 123fa5a..dc4aa0b 100644
--- a/docs_src/tutorial/many_to_many/tutorial002.py
+++ b/docs_src/tutorial/many_to_many/tutorial002.py
@@ -14,7 +14,7 @@ class HeroTeamLink(SQLModel, table=True):
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="teams", link_model=HeroTeamLink)
@@ -22,9 +22,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
teams: List[Team] = Relationship(back_populates="heroes", link_model=HeroTeamLink)
diff --git a/docs_src/tutorial/many_to_many/tutorial003.py b/docs_src/tutorial/many_to_many/tutorial003.py
index c2f3d56..1e03c4a 100644
--- a/docs_src/tutorial/many_to_many/tutorial003.py
+++ b/docs_src/tutorial/many_to_many/tutorial003.py
@@ -18,7 +18,7 @@ class HeroTeamLink(SQLModel, table=True):
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
hero_links: List[HeroTeamLink] = Relationship(back_populates="team")
@@ -26,9 +26,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_links: List[HeroTeamLink] = Relationship(back_populates="hero")
diff --git a/docs_src/tutorial/offset_and_limit/tutorial001.py b/docs_src/tutorial/offset_and_limit/tutorial001.py
index 5413c17..1b033ac 100644
--- a/docs_src/tutorial/offset_and_limit/tutorial001.py
+++ b/docs_src/tutorial/offset_and_limit/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/offset_and_limit/tutorial002.py b/docs_src/tutorial/offset_and_limit/tutorial002.py
index 9d85a13..65a6236 100644
--- a/docs_src/tutorial/offset_and_limit/tutorial002.py
+++ b/docs_src/tutorial/offset_and_limit/tutorial002.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/offset_and_limit/tutorial003.py b/docs_src/tutorial/offset_and_limit/tutorial003.py
index 5d2c3bf..36cae9c 100644
--- a/docs_src/tutorial/offset_and_limit/tutorial003.py
+++ b/docs_src/tutorial/offset_and_limit/tutorial003.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/offset_and_limit/tutorial004.py b/docs_src/tutorial/offset_and_limit/tutorial004.py
index bfa882d..a95715c 100644
--- a/docs_src/tutorial/offset_and_limit/tutorial004.py
+++ b/docs_src/tutorial/offset_and_limit/tutorial004.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial001.py b/docs_src/tutorial/one/tutorial001.py
index 9fa5f0b..072f4a3 100644
--- a/docs_src/tutorial/one/tutorial001.py
+++ b/docs_src/tutorial/one/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial002.py b/docs_src/tutorial/one/tutorial002.py
index a1d86e0..c244906 100644
--- a/docs_src/tutorial/one/tutorial002.py
+++ b/docs_src/tutorial/one/tutorial002.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial003.py b/docs_src/tutorial/one/tutorial003.py
index fe8c05c..f8fb0bc 100644
--- a/docs_src/tutorial/one/tutorial003.py
+++ b/docs_src/tutorial/one/tutorial003.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial004.py b/docs_src/tutorial/one/tutorial004.py
index 32bc9b9..8688fc4 100644
--- a/docs_src/tutorial/one/tutorial004.py
+++ b/docs_src/tutorial/one/tutorial004.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial005.py b/docs_src/tutorial/one/tutorial005.py
index 2382136..f624d4c 100644
--- a/docs_src/tutorial/one/tutorial005.py
+++ b/docs_src/tutorial/one/tutorial005.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial006.py b/docs_src/tutorial/one/tutorial006.py
index cf408c4..afc4854 100644
--- a/docs_src/tutorial/one/tutorial006.py
+++ b/docs_src/tutorial/one/tutorial006.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial007.py b/docs_src/tutorial/one/tutorial007.py
index 8a36d97..15df5ba 100644
--- a/docs_src/tutorial/one/tutorial007.py
+++ b/docs_src/tutorial/one/tutorial007.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial008.py b/docs_src/tutorial/one/tutorial008.py
index 1b0d6ef..9aa077c 100644
--- a/docs_src/tutorial/one/tutorial008.py
+++ b/docs_src/tutorial/one/tutorial008.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/one/tutorial009.py b/docs_src/tutorial/one/tutorial009.py
index 70deed2..f4ee23b 100644
--- a/docs_src/tutorial/one/tutorial009.py
+++ b/docs_src/tutorial/one/tutorial009.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py b/docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py
index d9851b4..fc4eb97 100644
--- a/docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py
+++ b/docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, sele
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship()
@@ -13,9 +13,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship()
diff --git a/docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py b/docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py
index b33fabe..a25df4e 100644
--- a/docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py
+++ b/docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, sele
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
@@ -13,9 +13,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py b/docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py
index cbd1581..c137f58 100644
--- a/docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py
+++ b/docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py
@@ -5,14 +5,14 @@ from sqlmodel import Field, Relationship, SQLModel, create_engine
class Weapon(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
hero: "Hero" = Relationship(back_populates="weapon")
class Power(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
hero_id: int = Field(foreign_key="hero.id")
hero: "Hero" = Relationship(back_populates="powers")
@@ -20,7 +20,7 @@ class Power(SQLModel, table=True):
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
@@ -28,9 +28,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py b/docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py
index 2bf2041..ec9c909 100644
--- a/docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py
+++ b/docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
@@ -13,9 +13,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py b/docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py
index 98c1919..71cb3f6 100644
--- a/docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py
+++ b/docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
@@ -13,9 +13,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py b/docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py
index e5c23a7..5f718ca 100644
--- a/docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py
+++ b/docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, sele
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
@@ -13,9 +13,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py b/docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py
index efae8e5..fdb436e 100644
--- a/docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py
+++ b/docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py
@@ -5,7 +5,7 @@ from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, sele
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="team")
@@ -13,9 +13,9 @@ class Team(SQLModel, table=True):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="heroes")
diff --git a/docs_src/tutorial/update/tutorial001.py b/docs_src/tutorial/update/tutorial001.py
index 96c7208..37868ac 100644
--- a/docs_src/tutorial/update/tutorial001.py
+++ b/docs_src/tutorial/update/tutorial001.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/update/tutorial002.py b/docs_src/tutorial/update/tutorial002.py
index 04185f8..4880f73 100644
--- a/docs_src/tutorial/update/tutorial002.py
+++ b/docs_src/tutorial/update/tutorial002.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/update/tutorial003.py b/docs_src/tutorial/update/tutorial003.py
index c319915..fd2ed75 100644
--- a/docs_src/tutorial/update/tutorial003.py
+++ b/docs_src/tutorial/update/tutorial003.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/docs_src/tutorial/update/tutorial004.py b/docs_src/tutorial/update/tutorial004.py
index e61a04f..868c66c 100644
--- a/docs_src/tutorial/update/tutorial004.py
+++ b/docs_src/tutorial/update/tutorial004.py
@@ -5,9 +5,9 @@ from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
- name: str
+ name: str = Field(index=True)
secret_name: str
- age: Optional[int] = None
+ age: Optional[int] = Field(default=None, index=True)
sqlite_file_name = "database.db"
diff --git a/mkdocs.yml b/mkdocs.yml
index 41b44b6..13744db 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -19,6 +19,7 @@ theme:
features:
- search.suggest
- search.highlight
+ - content.tabs.link
icon:
repo: fontawesome/brands/github-alt
logo: img/icon-white.svg
@@ -43,6 +44,7 @@ nav:
- tutorial/automatic-id-none-refresh.md
- tutorial/select.md
- tutorial/where.md
+ - tutorial/indexes.md
- tutorial/one.md
- tutorial/limit-and-offset.md
- tutorial/update.md
@@ -103,7 +105,8 @@ markdown_extensions:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_div_format ''
-- pymdownx.tabbed
+- pymdownx.tabbed:
+ alternate_style: true
- mdx_include
extra:
diff --git a/sqlmodel/main.py b/sqlmodel/main.py
index 08eaf59..12f30ba 100644
--- a/sqlmodel/main.py
+++ b/sqlmodel/main.py
@@ -426,7 +426,7 @@ def get_column_from_field(field: ModelField) -> Column: # type: ignore
nullable = not field.required
index = getattr(field.field_info, "index", Undefined)
if index is Undefined:
- index = True
+ index = False
if hasattr(field.field_info, "nullable"):
field_nullable = getattr(field.field_info, "nullable")
if field_nullable != Undefined:
diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py
index ac85eca..cf00856 100644
--- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py
+++ b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py
@@ -1,4 +1,6 @@
from fastapi.testclient import TestClient
+from sqlalchemy import inspect
+from sqlalchemy.engine.reflection import Inspector
from sqlmodel import create_engine
from sqlmodel.pool import StaticPool
@@ -166,3 +168,16 @@ def test_tutorial(clear_sqlmodel):
assert response.status_code == 200, response.text
assert data == openapi_schema
+
+ # Test inherited indexes
+ insp: Inspector = inspect(mod.engine)
+ indexes = insp.get_indexes(str(mod.Hero.__tablename__))
+ expected_indexes = [
+ {"name": "ix_hero_name", "column_names": ["name"], "unique": 0},
+ {"name": "ix_hero_age", "column_names": ["age"], "unique": 0},
+ ]
+ for index in expected_indexes:
+ assert index in indexes, "This expected index should be in the indexes in DB"
+ # Now that this index was checked, remove it from the list of indexes
+ indexes.pop(indexes.index(index))
+ assert len(indexes) == 0, "The database should only have the expected indexes"
diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py
index 421a1ca..57393a7 100644
--- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py
@@ -1,4 +1,6 @@
from fastapi.testclient import TestClient
+from sqlalchemy import inspect
+from sqlalchemy.engine.reflection import Inspector
from sqlmodel import create_engine
from sqlmodel.pool import StaticPool
@@ -166,3 +168,16 @@ def test_tutorial(clear_sqlmodel):
assert response.status_code == 200, response.text
assert data == openapi_schema
+
+ # Test inherited indexes
+ insp: Inspector = inspect(mod.engine)
+ indexes = insp.get_indexes(str(mod.Hero.__tablename__))
+ expected_indexes = [
+ {"name": "ix_hero_age", "column_names": ["age"], "unique": 0},
+ {"name": "ix_hero_name", "column_names": ["name"], "unique": 0},
+ ]
+ for index in expected_indexes:
+ assert index in indexes, "This expected index should be in the indexes in DB"
+ # Now that this index was checked, remove it from the list of indexes
+ indexes.pop(indexes.index(index))
+ assert len(indexes) == 0, "The database should only have the expected indexes"
diff --git a/tests/test_tutorial/test_indexes/__init__.py b/tests/test_tutorial/test_indexes/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_tutorial/test_indexes/test_tutorial001.py b/tests/test_tutorial/test_indexes/test_tutorial001.py
new file mode 100644
index 0000000..5962077
--- /dev/null
+++ b/tests/test_tutorial/test_indexes/test_tutorial001.py
@@ -0,0 +1,35 @@
+from unittest.mock import patch
+
+from sqlalchemy import inspect
+from sqlalchemy.engine.reflection import Inspector
+from sqlmodel import create_engine
+
+from ...conftest import get_testing_print_function
+
+
+def test_tutorial(clear_sqlmodel):
+ from docs_src.tutorial.indexes import tutorial001 as mod
+
+ mod.sqlite_url = "sqlite://"
+ mod.engine = create_engine(mod.sqlite_url)
+ calls = []
+
+ new_print = get_testing_print_function(calls)
+
+ with patch("builtins.print", new=new_print):
+ mod.main()
+ assert calls == [
+ [{"secret_name": "Dive Wilson", "age": None, "id": 1, "name": "Deadpond"}]
+ ]
+
+ insp: Inspector = inspect(mod.engine)
+ indexes = insp.get_indexes(str(mod.Hero.__tablename__))
+ expected_indexes = [
+ {"name": "ix_hero_name", "column_names": ["name"], "unique": 0},
+ {"name": "ix_hero_age", "column_names": ["age"], "unique": 0},
+ ]
+ for index in expected_indexes:
+ assert index in indexes, "This expected index should be in the indexes in DB"
+ # Now that this index was checked, remove it from the list of indexes
+ indexes.pop(indexes.index(index))
+ assert len(indexes) == 0, "The database should only have the expected indexes"
diff --git a/tests/test_tutorial/test_indexes/test_tutorial006.py b/tests/test_tutorial/test_indexes/test_tutorial006.py
new file mode 100644
index 0000000..e26f8b2
--- /dev/null
+++ b/tests/test_tutorial/test_indexes/test_tutorial006.py
@@ -0,0 +1,36 @@
+from unittest.mock import patch
+
+from sqlalchemy import inspect
+from sqlalchemy.engine.reflection import Inspector
+from sqlmodel import create_engine
+
+from ...conftest import get_testing_print_function
+
+
+def test_tutorial(clear_sqlmodel):
+ from docs_src.tutorial.indexes import tutorial002 as mod
+
+ mod.sqlite_url = "sqlite://"
+ mod.engine = create_engine(mod.sqlite_url)
+ calls = []
+
+ new_print = get_testing_print_function(calls)
+
+ with patch("builtins.print", new=new_print):
+ mod.main()
+ assert calls == [
+ [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}],
+ [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}],
+ ]
+
+ insp: Inspector = inspect(mod.engine)
+ indexes = insp.get_indexes(str(mod.Hero.__tablename__))
+ expected_indexes = [
+ {"name": "ix_hero_name", "column_names": ["name"], "unique": 0},
+ {"name": "ix_hero_age", "column_names": ["age"], "unique": 0},
+ ]
+ for index in expected_indexes:
+ assert index in indexes, "This expected index should be in the indexes in DB"
+ # Now that this index was checked, remove it from the list of indexes
+ indexes.pop(indexes.index(index))
+ assert len(indexes) == 0, "The database should only have the expected indexes"
diff --git a/tests/test_tutorial/test_where/test_tutorial003.py b/tests/test_tutorial/test_where/test_tutorial003.py
index a01955e..4794d84 100644
--- a/tests/test_tutorial/test_where/test_tutorial003.py
+++ b/tests/test_tutorial/test_where/test_tutorial003.py
@@ -17,7 +17,7 @@ def test_tutorial(clear_sqlmodel):
with patch("builtins.print", new=new_print):
mod.main()
- assert calls == [
+ expected_calls = [
[{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}],
[{"id": 3, "name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48}],
[
@@ -29,3 +29,8 @@ def test_tutorial(clear_sqlmodel):
}
],
]
+ for call in expected_calls:
+ assert call in calls, "This expected item should be in the list"
+ # Now that this item was checked, remove it from the list
+ calls.pop(calls.index(call))
+ assert len(calls) == 0, "The list should only have the expected items"
diff --git a/tests/test_tutorial/test_where/test_tutorial004.py b/tests/test_tutorial/test_where/test_tutorial004.py
index 9f4f80c..682babd 100644
--- a/tests/test_tutorial/test_where/test_tutorial004.py
+++ b/tests/test_tutorial/test_where/test_tutorial004.py
@@ -16,7 +16,7 @@ def test_tutorial(clear_sqlmodel):
with patch("builtins.print", new=new_print):
mod.main()
- assert calls == [
+ expected_calls = [
[{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}],
[{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}],
[{"id": 3, "name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48}],
@@ -29,3 +29,8 @@ def test_tutorial(clear_sqlmodel):
}
],
]
+ for call in expected_calls:
+ assert call in calls, "This expected item should be in the list"
+ # Now that this item was checked, remove it from the list
+ calls.pop(calls.index(call))
+ assert len(calls) == 0, "The list should only have the expected items"
diff --git a/tests/test_tutorial/test_where/test_tutorial011.py b/tests/test_tutorial/test_where/test_tutorial011.py
index 743ecd5..8006cd0 100644
--- a/tests/test_tutorial/test_where/test_tutorial011.py
+++ b/tests/test_tutorial/test_where/test_tutorial011.py
@@ -16,7 +16,7 @@ def test_tutorial(clear_sqlmodel):
with patch("builtins.print", new=new_print):
mod.main()
- assert calls == [
+ expected_calls = [
[{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}],
[{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}],
[{"id": 3, "name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48}],
@@ -29,3 +29,8 @@ def test_tutorial(clear_sqlmodel):
}
],
]
+ for call in expected_calls:
+ assert call in calls, "This expected item should be in the list"
+ # Now that this item was checked, remove it from the list
+ calls.pop(calls.index(call))
+ assert len(calls) == 0, "The list should only have the expected items"