✨ Document indexes and make them opt-in (#205)
97
docs/img/tutorial/indexes/dictionary001.drawio
Normal file
@ -0,0 +1,97 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1463" dy="1403" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="68" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="580" y="1030" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
57
docs/img/tutorial/indexes/dictionary001.svg
Normal file
After Width: | Height: | Size: 30 KiB |
97
docs/img/tutorial/indexes/dictionary002.drawio
Normal file
@ -0,0 +1,97 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1707" dy="1637" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeWidth=3;strokeColor=#b85450;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="68" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="1030" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/dictionary002.svg
Normal file
After Width: | Height: | Size: 28 KiB |
97
docs/img/tutorial/indexes/dictionary003.drawio
Normal file
@ -0,0 +1,97 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1205" dy="1155" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeWidth=3;strokeColor=#b85450;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="69" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="580" y="1030" width="560" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/dictionary003.svg
Normal file
After Width: | Height: | Size: 27 KiB |
100
docs/img/tutorial/indexes/dictionary004.drawio
Normal file
@ -0,0 +1,100 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1463" dy="1403" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="68" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="1030" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="69" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="1030" width="560" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/dictionary004.svg
Normal file
After Width: | Height: | Size: 28 KiB |
97
docs/img/tutorial/indexes/dictionary005.drawio
Normal file
@ -0,0 +1,97 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1024" dy="982" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeWidth=3;strokeColor=#b85450;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="69" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="1030" width="840" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/dictionary005.svg
Normal file
After Width: | Height: | Size: 27 KiB |
100
docs/img/tutorial/indexes/dictionary006.drawio
Normal file
@ -0,0 +1,100 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1024" dy="982" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="69" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="1030" width="840" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="70" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="180" y="1030" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/dictionary006.svg
Normal file
After Width: | Height: | Size: 28 KiB |
100
docs/img/tutorial/indexes/dictionary007.drawio
Normal file
@ -0,0 +1,100 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1024" dy="982" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeWidth=3;strokeColor=#b85450;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="69" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="1030" width="840" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="71" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="1030" width="120" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/dictionary007.svg
Normal file
After Width: | Height: | Size: 27 KiB |
103
docs/img/tutorial/indexes/dictionary008.drawio
Normal file
@ -0,0 +1,103 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1024" dy="982" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="950" width="1040" height="160" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="<font style="font-size: 24px">A</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="<font style="font-size: 24px">B</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="<font style="font-size: 24px">C</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeWidth=3;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="<font style="font-size: 24px">E</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="<font style="font-size: 24px">F</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="300" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="<font style="font-size: 24px">G</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="340" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="<font style="font-size: 24px">H</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="<font style="font-size: 24px">I</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="<font style="font-size: 24px">J</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="460" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="<font style="font-size: 24px">K</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="<font style="font-size: 24px">L</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="<font style="font-size: 24px">M</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="<font style="font-size: 24px">N</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="<font style="font-size: 24px">O</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="<font style="font-size: 24px">P</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="<font style="font-size: 24px">Q</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="740" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="56" value="<font style="font-size: 24px">R</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="780" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="57" value="<font style="font-size: 24px">S</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="820" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="58" value="<font style="font-size: 24px">T</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="59" value="<font style="font-size: 24px">U</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="900" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="60" value="<font style="font-size: 24px">V</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="940" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="61" value="<font style="font-size: 24px">W</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="62" value="<font style="font-size: 24px">X</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1020" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="63" value="<font style="font-size: 24px">Y</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1060" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="64" value="<font style="font-size: 24px">Z</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1100" y="840" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Dictionary</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="565" y="960" width="110" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="69" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="1030" width="880" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="71" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeWidth=3;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="1030" width="120" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="72" value="<font style="font-size: 24px">D</font>" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeWidth=3;strokeColor=#82b366;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="1030" width="40" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/dictionary008.svg
Normal file
After Width: | Height: | Size: 28 KiB |
92
docs/img/tutorial/indexes/techbook001.drawio
Normal file
@ -0,0 +1,92 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="objTApYHlBqCKos3M7rL" name="Page-1">
|
||||
<mxGraphModel dx="1707" dy="1637" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="420" width="1020" height="490" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="66" value="<font style="font-size: 24px">Technical Book</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="492.5" y="440" width="195" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="77" value="<font style="font-size: 24px">Chapter 1</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="490" width="140" height="90" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="83" value="<font style="font-size: 24px">Chapter 2</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="490" width="140" height="90" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="84" value="<font style="font-size: 24px">Chapter 3</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="380" y="490" width="140" height="90" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="85" value="<font style="font-size: 24px">Chapter 4</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="520" y="490" width="140" height="90" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="86" value="<font style="font-size: 24px">Chapter 5</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="660" y="490" width="140" height="90" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="87" value="<font style="font-size: 24px">Chapter 6</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="800" y="490" width="140" height="90" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="88" value="<font style="font-size: 24px">Chapter 7</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="940" y="490" width="140" height="90" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="74" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeWidth=3;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="580" width="980" height="310" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="75" value="<font style="font-size: 24px">Book Index</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="498.125" y="840" width="183.75" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="89" style="edgeStyle=orthogonalEdgeStyle;html=1;strokeWidth=3;" edge="1" parent="1" source="42" target="77">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="92" style="edgeStyle=orthogonalEdgeStyle;html=1;strokeWidth=3;" edge="1" parent="1" source="42" target="86">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="<font style="font-size: 24px">Database</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="119.99615384615385" y="690" width="150.76923076923077" height="70" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="94" style="edgeStyle=orthogonalEdgeStyle;html=1;strokeWidth=3;" edge="1" parent="1" source="93" target="83">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="330" y="820"/>
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="95" style="edgeStyle=orthogonalEdgeStyle;html=1;strokeWidth=3;" edge="1" parent="1" source="93" target="85">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="590" y="800"/>
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="93" value="<font style="font-size: 24px">Python</font>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="909.9961538461539" y="780" width="150.76923076923077" height="70" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="97" style="edgeStyle=orthogonalEdgeStyle;html=1;strokeWidth=3;" edge="1" parent="1" source="96" target="87">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="98" style="edgeStyle=orthogonalEdgeStyle;html=1;strokeWidth=3;" edge="1" parent="1" source="96" target="86">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="770" y="725"/>
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="96" value="<span style="font-size: 24px">Files</span>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="909.9961538461539" y="690" width="150.76923076923077" height="70" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="100" style="edgeStyle=orthogonalEdgeStyle;html=1;strokeWidth=3;" edge="1" parent="1" source="99" target="84">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="450" y="800"/>
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="99" value="<span style="font-size: 24px">Editors</span>" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=3;" vertex="1" parent="1">
|
||||
<mxGeometry x="119.9961538461539" y="780" width="150.76923076923077" height="70" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
1
docs/img/tutorial/indexes/techbook001.svg
Normal file
After Width: | Height: | Size: 17 KiB |
@ -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.
|
||||
|
@ -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 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
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.
|
||||
|
406
docs/tutorial/indexes.md
Normal file
@ -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.
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python hl_lines="8 10"
|
||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
..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.
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary001.svg">
|
||||
|
||||
You know that in the alphabet, the letter `d` for `database` comes **before** the letter `m` for `manual`.
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary002.svg">
|
||||
|
||||
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.
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary003.svg">
|
||||
|
||||
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`.
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary004.svg">
|
||||
|
||||
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.
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary005.svg">
|
||||
|
||||
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`.
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary006.svg">
|
||||
|
||||
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.
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary007.svg">
|
||||
|
||||
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`. 🎉
|
||||
|
||||
<img src="/img/tutorial/indexes/dictionary008.svg">
|
||||
|
||||
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 <abbr title="a recipe, a sequence of predefined steps that achieve a result">algorithm</abbr> 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.
|
||||
|
||||
<img src="/img/tutorial/indexes/techbook001.svg">
|
||||
|
||||
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:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>id</th><th>name</th><th>secret_name</th><th>age</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td><td>Deadpond</td><td>Dive Wilson</td><td>null</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td><td>Spider-Boy</td><td>Pedro Parqueador</td><td>null</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td><td>Rusty-Man</td><td>Tommy Sharp</td><td>48</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
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:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>name</th><th>id</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deadpond</td><td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rusty-Man</td><td>3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spider-Boy</td><td>2</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
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.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>name</th><th>id</th>
|
||||
</tr>
|
||||
<tr style="background-color: #F5F5F5; color: #999999;">
|
||||
<td>Deadpond</td><td>1</td>
|
||||
</tr>
|
||||
<tr style="background-color: #F5F5F5; color: #999999;">
|
||||
<td>Rusty-Man</td><td>3</td>
|
||||
</tr>
|
||||
<tr style="background-color: #FFF2CC;">
|
||||
<td>Spider-Boy</td><td>2</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
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:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>name</th><th>id</th>
|
||||
</tr>
|
||||
<tr style="background-color: #F5F5F5; color: #999999;">
|
||||
<td>Deadpond</td><td>1</td>
|
||||
</tr>
|
||||
<tr style="background-color: #F5F5F5; color: #999999;">
|
||||
<td>Rusty-Man</td><td>3</td>
|
||||
</tr>
|
||||
<tr style="background-color: #D5E8D4;">
|
||||
<td>✨ Spider-Boy ✨</td><td>2</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
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 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/where/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
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 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/indexes/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
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 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/indexes/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
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:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```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'
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## 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 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
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**.
|
@ -18,7 +18,7 @@ We'll continue with the same examples we have been using in the previous chapter
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/where/tutorial006.py!}
|
||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -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:
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/where/tutorial006.py!}
|
||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
@ -10,7 +10,7 @@ As before, we'll continue from where we left off with the previous code.
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!./docs_src/tutorial/where/tutorial006.py!}
|
||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
@ -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**. 😎
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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):
|
||||
|
@ -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"
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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):
|
||||
|
0
docs_src/tutorial/indexes/__init__.py
Normal file
51
docs_src/tutorial/indexes/tutorial001.py
Normal file
@ -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()
|
59
docs_src/tutorial/indexes/tutorial002.py
Normal file
@ -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()
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
0
tests/test_tutorial/test_indexes/__init__.py
Normal file
35
tests/test_tutorial/test_indexes/test_tutorial001.py
Normal file
@ -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"
|
36
tests/test_tutorial/test_indexes/test_tutorial006.py
Normal file
@ -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"
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|