Skip to content

Commit 235eaed

Browse files
CRUD tutorial
1 parent ee8f770 commit 235eaed

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
= Writing and updating data in TypeDB
2+
:keywords: typedb, typeql, tutorial, console, crud
3+
:pageTitle:
4+
:summary:
5+
:page-toclevels: 2
6+
:tabs-sync-option:
7+
:test-typeql: linear
8+
9+
== Overview
10+
11+
This tutorial covers the basics of writing and updating data in TypeDB.
12+
13+
== Prerequisites
14+
15+
This tutorial assumes you have access to a running TypeDB instance, as well as a TypeDB Console.
16+
17+
We recommend xref:{page-version}@home::install/ce.adoc[installing TypeDB Community Edition] as it is distributed bundled with Console for easy setup.
18+
19+
This is a continuation of xref:{page-version}@tutorials::pipelines-read.adoc[], though you don't need to have completed it to follow along.
20+
21+
== Example schema and data
22+
23+
IMPORTANT: TODO PERMALINKS TO `typedb/typedb-examples`
24+
25+
We are using the https://github.com/typedb/typedb-examples/tree/master/use-cases/bookstore[bookstore example] schema and data throughout this tutorial.
26+
You can load the example into your TypeDB instance using the following Console command:
27+
28+
[,console]
29+
----
30+
database create-init bookstore http://github.com/typedb/typedb-examples/releases/latest/download/bookstore-schema.tql http://github.com/typedb/typedb-examples/releases/latest/download/bookstore-data.tql
31+
----
32+
33+
.Full schema and data queries
34+
[%collapsible]
35+
====
36+
[,typeql]
37+
----
38+
#!test[schema, commit]
39+
include::{page-version}@academy::attachment$bookstore-schema.tql[lines=20..]
40+
----
41+
[,typeql]
42+
----
43+
#!test[write, commit]
44+
include::{page-version}@academy::attachment$bookstore-data.tql[lines=18..]
45+
----
46+
====
47+
48+
== Add a book to the database with `insert`
49+
50+
To add a new book to the database, we can use an xref:{page-version}@typeql-reference::pipelines/insert.adoc[`insert`] query.
51+
Simply use an xref:{page-version}@typeql-reference::statements/isa.adoc[`isa`] statement to specify the type of the entity, and then use
52+
xref:{page-version}@typeql-reference::statements/has.adoc[`has`] statements to list the attributes of the book.
53+
54+
[,typeql]
55+
----
56+
#!test[write, count = 1, rollback]
57+
insert
58+
$book isa paperback,
59+
has isbn-13 "9780441569595",
60+
has isbn-10 "0441569595",
61+
has title "Neuromancer",
62+
has page-count 288,
63+
has price 6.99,
64+
has genre "fiction",
65+
has genre "science fiction",
66+
has stock 5;
67+
----
68+
69+
Adding the author is as simple as inserting a `contributor` entity in a similar fashion, and an `authoring` relation linking the two.
70+
71+
[,typeql]
72+
----
73+
#!test[write, count = 1, commit]
74+
insert
75+
$book isa paperback,
76+
has isbn-13 "9780441569595",
77+
has isbn-10 "0441569595",
78+
has title "Neuromancer",
79+
has page-count 288,
80+
has price 6.99,
81+
has genre "fiction",
82+
has genre "science fiction",
83+
has stock 5;
84+
$author isa contributor,
85+
has name "Gibson, William";
86+
(work: $book, author: $author) isa authoring;
87+
----
88+
89+
What if the author already exists?
90+
The query above would then merrily insert another `contributor` with the same name, which is almost certainly not what we intend.
91+
92+
Thankfully, the fix is straightforward.
93+
We can use a xref:{page-version}@typeql-reference::pipelines/match.adoc[`match`] stage to find the author, and then use an xref:{page-version}@typeql-reference::pipelines/insert.adoc[`insert`] stage
94+
to create the book and the authoring relation.
95+
96+
[,typeql]
97+
----
98+
#!test[write, count = 1, rollback]
99+
match
100+
$author isa contributor,
101+
has name "Adams, Douglas";
102+
insert
103+
$book isa paperback,
104+
has isbn-13 "9781529034585",
105+
has isbn-10 "1529034582",
106+
has title "Dirk Gently's Holistic Detective Agency",
107+
has page-count 288,
108+
has price 5.99,
109+
has genre "fiction",
110+
has genre "science fiction",
111+
has stock 4;
112+
(work: $book, author: $author) isa authoring;
113+
----
114+
115+
== Insert an author only if one doesn't exist with `put`
116+
117+
We happened to know that an author named "Adams, Douglas" was already present in the database.
118+
What if we didn't know that, but still wanted to avoid inserting a duplicate author?
119+
We can use a xref:{page-version}@typeql-reference::pipelines/put.adoc[`put`] clause to insert the author only if a `contributor` matching the constraints does not already exist in the database.
120+
121+
[,typeql]
122+
----
123+
#!test[write, count = 1, rollback]
124+
put
125+
$author isa contributor,
126+
has name "Adams, Douglas";
127+
insert
128+
$book isa paperback,
129+
has isbn-13 "9781529034585",
130+
has isbn-10 "1529034582",
131+
has title "Dirk Gently's Holistic Detective Agency",
132+
has page-count 288,
133+
has price 5.99,
134+
has genre "fiction",
135+
has genre "science fiction",
136+
has stock 4;
137+
(work: $book, author: $author) isa authoring;
138+
----
139+
140+
[TIP]
141+
====
142+
It might be tempting to combine all of the above into one `put` query:
143+
144+
[,typeql]
145+
----
146+
#!test[write, count = 1, rollback]
147+
put
148+
$author isa contributor,
149+
has name "Adams, Douglas";
150+
$book isa paperback,
151+
has isbn-13 "9781529034585",
152+
has isbn-10 "1529034582",
153+
has title "Dirk Gently's Holistic Detective Agency",
154+
has page-count 288,
155+
has price 5.99,
156+
has genre "fiction",
157+
has genre "science fiction",
158+
has stock 4;
159+
(work: $book, author: $author) isa authoring;
160+
----
161+
162+
It's important to remember that if anything in the `put` fails to match existing data, the entirety of `put` body is inserted.
163+
If the author already exists, but the book doesn't, a new entity for the author is inserted alongside the book.
164+
This is why it's important to keep `put` stages as short as possible, usually one per object.
165+
Here's an example with multiple ``put``s:
166+
167+
[,typeql]
168+
----
169+
#!test[write, count = 1, rollback]
170+
put
171+
$author isa contributor,
172+
has name "Adams, Douglas";
173+
put
174+
$publisher isa publisher,
175+
has name "Signet";
176+
insert
177+
$book isa paperback,
178+
has isbn-13 "9781529034585",
179+
has isbn-10 "1529034582",
180+
has title "Dirk Gently's Holistic Detective Agency",
181+
has page-count 288,
182+
has price 5.99,
183+
has genre "fiction",
184+
has genre "science fiction",
185+
has stock 4;
186+
(work: $book, author: $author) isa authoring;
187+
(publisher: $publisher, published: $book) isa publishing;
188+
----
189+
====
190+
191+
== Update stock with `update`
192+
193+
When we sell a book, we need to decrease the stock by one.
194+
Concretely, that means deleting the old `stock` attribute and inserting a new one with the updated value.
195+
196+
[,typeql]
197+
----
198+
#!test[write, count = 1, commit]
199+
match
200+
$book isa book, has isbn-13 "9780671461492", has stock $stock;
201+
let $new-stock = $stock - 1;
202+
delete
203+
has $stock of $book;
204+
insert
205+
$book has stock == $new-stock;
206+
----
207+
208+
xref:{page-version}@typeql-reference::pipelines/update.adoc[`update`] is a shorthand for the above.
209+
210+
[,typeql]
211+
----
212+
#!test[write, count = 1, commit]
213+
match
214+
$book isa book, has isbn-13 "9780671461492", has stock $stock;
215+
let $new-stock = $stock - 1;
216+
update
217+
$book has stock == $new-stock;
218+
----
219+
220+
[TIP]
221+
====
222+
`update` is only allowed when the cardinality constraint of the attribute is at most one.
223+
This is to avoid ambiguity: there's at most one old attribute to delete.
224+
225+
By default, all attributes have cardinality `0..1`, but if you define an attribute ownership with higher cardinality, you will not be able to use `update` even if the object happens to only have zero
226+
or one attribute of the type.
227+
====
228+
229+
== Delete a book with `delete`
230+
231+
To delete a book, we can use a xref:{page-version}@typeql-reference::pipelines/delete.adoc[`delete`] query.
232+
233+
[,typeql]
234+
----
235+
#!test[write, count = 1, rollback]
236+
match
237+
$book isa book, has isbn-13 "9780671461492";
238+
delete
239+
$book;
240+
----
241+
242+
Note that while this query deletes all attributes of the book, it does not delete the relations in which the book is involved.
243+
The book is deleted _from_ the relations, but the relations themselves remain.
244+
245+
To delete all relations in which the book is involved as well as the book, we need to match them first:
246+
247+
[,typeql]
248+
----
249+
#!test[write, count = 3, commit]
250+
match
251+
$book isa book, has isbn-13 "9780671461492";
252+
$rel links ($book);
253+
delete
254+
$rel;
255+
$book;
256+
----
257+
258+
== Further reading
259+
260+
[cols-2]
261+
--
262+
.xref:{page-version}@tutorials::pipelines-advanced.adoc[]
263+
[.clickable]
264+
****
265+
Learn about complex pipelines in the next tutorial
266+
****
267+
268+
.xref:{page-version}@core-concepts::typeql/index.adoc[]
269+
[.clickable]
270+
****
271+
TypeQL core concepts
272+
****
273+
274+
.xref:{page-version}@typeql-reference::index.adoc[]
275+
[.clickable]
276+
****
277+
TypeQL reference manual
278+
****
279+
--

0 commit comments

Comments
 (0)