github.com/dgraph-io/dgraph@v1.2.8/wiki/content/tutorial-3/index.md (about) 1 +++ 2 title = "Get Started with Dgraph - Basic Types and Operations on them" 3 +++ 4 5 **Welcome to the third tutorial of getting started with Dgraph.** 6 7 In the [previous tutorial]({{< relref "tutorial-2/index.md" >}}) of getting started, 8 we learned about the CRUD operations using UIDs. 9 We also learned about traversals and recursive traversals. 10 11 In this tutorial, we'll learn about Dgraph's basic types and how to query for them. 12 Specifically, we'll learn about: 13 14 - Basic data types in Dgraph. 15 - Querying for predicate values. 16 - Indexing. 17 - Filtering nodes. 18 - Traversing in reverse direction. 19 20 You can see the accompanying video below. 21 22 {{< youtube f401or0hg5E >}} 23 24 ---- 25 26 Let's start by building the following graph of a simple blog application. 27 Here's the Graph model of our application 28 29 {{% load-img "/images/tutorials/3/a-main-graph.JPG" "main graph model" %}} 30 31 The above graph has three entities: Author, Blog posts, and Tags. 32 The nodes in the graph represent these entities. 33 For the rest of the tutorial, we'll call the node representing a blog as a `blog post` node. 34 And the node presenting a `tag` as a `tag node`, and so on. 35 36 You can see from the graph model that these entities are related: 37 38 - Every Author has one or more blog posts. 39 40 The `published` edge relates the blogs to their authors. 41 These edges start from an `author node` and point to a `blog post` node. 42 43 - Every Blog post has one or more tags. 44 45 The `tagged` edge relates the blog posts to their tags. 46 These edges emerge from a `blog post node` and point to a `tag node`. 47 48 Let's build our Graph. 49 50 Go to Ratel, click on the mutate tab, paste the following mutation, and click Run. 51 52 ```json 53 { 54 "set": [ 55 { 56 "author_name": "John Campbell", 57 "rating": 4.1, 58 "published": [ 59 { 60 "title": "Dgraph's recap of GraphQL Conf - Berlin 2019", 61 "url": "https://blog.dgraph.io/post/graphql-conf-19/", 62 "content": "We took part in the recently held GraphQL conference in Berlin. The experience was fascinating, and we were amazed by the high voltage enthusiasm in the GraphQL community. Now, we couldn’t help ourselves from sharing this with Dgraph’s community! This is the story of the GraphQL conference in Berlin.", 63 "likes": 100, 64 "dislikes": 4, 65 "publish_time": "2018-06-25T02:30:00", 66 "tagged": [ 67 { 68 "uid": "_:graphql", 69 "tag_name": "graphql" 70 }, 71 { 72 "uid": "_:devrel", 73 "tag_name": "devrel" 74 } 75 ] 76 }, 77 { 78 "title": "Dgraph Labs wants you!", 79 "url": "https://blog.dgraph.io/post/hiring-19/", 80 "content": "We recently announced our successful Series A fundraise and, since then, many people have shown interest to join our team. We are very grateful to have so many people interested in joining our team! We also realized that the job openings were neither really up to date nor covered all of the roles that we are looking for. This is why we decided to spend some time rewriting them and the result is these six new job openings!.", 81 "likes": 60, 82 "dislikes": 2, 83 "publish_time": "2018-08-25T03:45:00", 84 "tagged": [ 85 { 86 "uid": "_:hiring", 87 "tag_name": "hiring" 88 }, 89 { 90 "uid": "_:careers", 91 "tag_name": "careers" 92 } 93 ] 94 } 95 ] 96 }, 97 { 98 "author_name": "John Travis", 99 "rating": 4.5, 100 "published": [ 101 { 102 "title": "How Dgraph Labs Raised Series A", 103 "url": "https://blog.dgraph.io/post/how-dgraph-labs-raised-series-a/", 104 "content": "I’m really excited to announce that Dgraph has raised $11.5M in Series A funding. This round is led by Redpoint Ventures, with investment from our previous lead, Bain Capital Ventures, and participation from all our existing investors – Blackbird, Grok and AirTree. With this round, Satish Dharmaraj joins Dgraph’s board of directors, which includes Salil Deshpande from Bain and myself. Their guidance is exactly what we need as we transition from building a product to bringing it to market. So, thanks to all our investors!.", 105 "likes": 139, 106 "dislikes": 6, 107 "publish_time": "2019-07-11T01:45:00", 108 "tagged": [ 109 { 110 "uid": "_:annoucement", 111 "tag_name": "annoucement" 112 }, 113 { 114 "uid": "_:funding", 115 "tag_name": "funding" 116 } 117 ] 118 }, 119 { 120 "title": "Celebrating 10,000 GitHub Stars", 121 "url": "https://blog.dgraph.io/post/10k-github-stars/", 122 "content": "Dgraph is celebrating the milestone of reaching 10,000 GitHub stars 🎉. This wouldn’t have happened without all of you, so we want to thank the awesome community for being with us all the way along. This milestone comes at an exciting time for Dgraph.", 123 "likes": 33, 124 "dislikes": 12, 125 "publish_time": "2017-03-11T01:45:00", 126 "tagged": [ 127 { 128 "uid": "_:devrel" 129 }, 130 { 131 "uid": "_:annoucement" 132 } 133 ] 134 } 135 ] 136 }, 137 { 138 "author_name": "Katie Perry", 139 "rating": 3.9, 140 "published": [ 141 { 142 "title": "Migrating data from SQL to Dgraph!", 143 "url": "https://blog.dgraph.io/post/migrating-from-sql-to-dgraph/", 144 "content": "Dgraph is rapidly gaining reputation as an easy to use database to build apps upon. Many new users of Dgraph have existing relational databases that they want to migrate from. In particular, we get asked a lot about how to migrate data from MySQL to Dgraph. In this article, we present a tool that makes this migration really easy: all a user needs to do is write a small 3 lines configuration file and type in 2 commands. In essence, this tool bridges one of the best technologies of the 20th century with one of the best ones of the 21st (if you ask us).", 145 "likes": 20, 146 "dislikes": 1, 147 "publish_time": "2018-08-25T01:44:00", 148 "tagged": [ 149 { 150 "uid": "_:tutorial", 151 "tag_name": "tutorial" 152 } 153 ] 154 }, 155 { 156 "title": "Building a To-Do List React App with Dgraph", 157 "url": "https://blog.dgraph.io/post/building-todo-list-react-dgraph/", 158 "content": "In this tutorial we will build a To-Do List application using React JavaScript library and Dgraph as a backend database. We will use dgraph-js-http — a library designed to greatly simplify the life of JavaScript developers when accessing Dgraph databases.", 159 "likes": 97, 160 "dislikes": 5, 161 "publish_time": "2019-02-11T03:33:00", 162 "tagged": [ 163 { 164 "uid": "_:tutorial" 165 }, 166 { 167 "uid": "_:devrel" 168 }, 169 { 170 "uid": "_:javascript", 171 "tag_name": "javascript" 172 } 173 ] 174 } 175 ] 176 } 177 ] 178 } 179 ``` 180 181 Our Graph is ready! 182 183 {{% load-img "/images/tutorials/3/l-fullgraph-2.png" "rating-blog-rating" %}} 184 185 Our Graph has: 186 187 - Three blue author nodes. 188 - Each author has two blog posts each, six in total, which are represented by the green nodes. 189 - The tags of the blog posts are in pink. 190 You can see that there are 8 unique tags, and some of the blogs share a common tag. 191 192 193 ## Data types for predicates 194 195 Dgraph automatically detects the data type of its predicates. 196 You can see the auto-detected data types using the Ratel UI. 197 198 Click on the schema tab on the left and then check the `Type` column. 199 You'll see the predicate names and their corresponding data types. 200 201 {{% load-img "/images/tutorials/3/a-initial.png" "rating-blog-rating" %}} 202 203 These data types include `string`, `float`, and `int` and `uid`. 204 Besides them, Dgraph also offers three more basic data types: `geo`, `dateTime`, and `bool`. 205 206 The `uid` type represents predicates between two nodes. 207 In other words, they represent edges connecting two nodes. 208 209 You might have noticed that the `published` and `tagged` predicates are of type `uid` array (`[uid]`). 210 UID arrays represent a collection of UIDs. 211 This is used to represent one to many relationships. 212 213 For instance, we know that an author can publish more than one blog. 214 Hence, there could be more than one `published` edge emerging from a given `author` node. 215 Each pointing to a different blog post of the author. 216 217 Dgraph's [v1.1 release](https://blog.dgraph.io/post/release-v1.1.0/) introduced type system feature. 218 This feature made it possible to create custom data types by grouping one or more predicates. 219 But in this tutorial, we'll only focus on the basic data types. 220 221 222 Also, notice that there are no entries in the indices column. 223 We'll talk about indices in detail shortly. 224 225 226 ## Querying for predicate values 227 228 First, let's query for all the Authors and their ratings. 229 230 ``` 231 { 232 authors_and_ratings(func: has(author_name)) { 233 uid 234 author_name 235 rating 236 } 237 } 238 ``` 239 240 {{% load-img "/images/tutorials/3/a-find-rating-2.png" "authors" %}} 241 242 Refer to the [first episode]({{< relref "tutorial-1/index.md" >}}) if you have any questions related to the structure of the query in general. 243 244 We have 3 authors in total in our dataset. 245 Now, let's find the best authors. 246 Let's query for authors whose rating is 4.0 or more. 247 248 In order to achieve it, we need a way to select nodes that meet certain criteria (e.g., rating > 4.0). 249 You can do so by using Dgraph's built-in comparator functions. 250 Here's the list of comparator functions available in Dgraph. 251 252 | comparator function name | Full form | 253 |--------------------------|--------------------------| 254 | eq | equals to | 255 | lt | less than | 256 | le | less than or equal to | 257 | gt | greater than | 258 | ge | greater than or equal to | 259 260 261 There are a total of five comparator functions in Dgraph. 262 You can use any of them alongside the `func` keyword in your queries. 263 264 The comparator function take two arguments. 265 One is the predicate name, and the other is its value to compare. 266 Here are a few examples. 267 268 | Example usage | Description | 269 |--------------------------|----------------------------------------------------------------------------| 270 | func: eq(age, 60) | Return nodes with `age` predicate equal to 60. | 271 | func: gt(likes, 100) | Return nodes with a value of `likes` predicate greater than 100. | 272 | func: le(dislikes, 10) | Return nodes with a value of `dislikes` predicates less than or equal to 10. | 273 274 275 Now, guess the comparator function we should use to select `author nodes` with a rating of 4.0 or more. 276 277 If you think it should be `greater than or equal to(ge)` function, then you're right! 278 279 Let's try it out. 280 281 ```graphql 282 { 283 best_authors(func: ge(rating, 4.0)) { 284 uid 285 author.name 286 rating 287 } 288 } 289 ``` 290 291 {{% load-img "/images/tutorials/3/b-index-missing.png" "index missing" %}} 292 293 We got an error! The index for the `rating` predicate is missing. 294 You cannot query for the value of a predicate unless you've added an index for it. 295 296 Let's learn more about indices in Dgraph and also how to add them. 297 298 ## Indexing in Dgraph 299 300 Indices are used to speed up your queries on predicates. 301 They have to be explicitly added to a predicate when they are required. 302 That is, only when you need to query for the value of a predicate. 303 304 Also, there's no need to anticipate the indices to be added right at the beginning. 305 You can add them as you go. 306 307 Dgraph offers different types of indices. 308 The choice of the index to be added depends on the data type of the predicate. 309 310 Here is the table containing data types and the set of indices that can be applied to them. 311 312 | Data type | Available index types | 313 |-----------|-----------------------------| 314 | int | int | 315 | float | float | 316 | string | hash, exact, term, fulltext, trigram | 317 | bool | bool | 318 | geo | geo | 319 | dateTime | year, month, day, hour | 320 321 Only `string` and `dateTime` data types have an option for more than one index type. 322 323 Let's create an index on the rating predicate. 324 Ratel UI makes it super simple to add an index. 325 326 Here's the sequence of steps: 327 328 - Go to the schema tab on the left. 329 - Click on the `rating` predicate from the list. 330 - Tick the index option in the Properties UI on the right. 331 332 {{% load-img "/images/tutorials/3/c-add-schema.png" "Add schema" %}} 333 334 We successfully added the index for `rating` predicate! 335 Let's rerun our previous query. 336 337 {{% load-img "/images/tutorials/3/d-rating-query.png" "rating" %}} 338 339 We successfully queried for author nodes with a rating of 4.0 or more. 340 341 How about we also fetch the blog posts of these authors? 342 343 We already know that the `published` edge points from an `author` node to a `blog post` node. 344 So fetching the blog posts of the `author` nodes is simple. 345 We need to just traverse the `published` edge starting from the `author` nodes. 346 347 348 ```graphql 349 { 350 authors_and_ratings(func: ge(rating, 4.0)) { 351 uid 352 author_name 353 rating 354 published { 355 title 356 content 357 dislikes 358 } 359 } 360 } 361 ``` 362 363 {{% load-img "/images/tutorials/3/e-rating-blog.png" "rating-blog-rating" %}} 364 365 _Check out our [previous tutorial]{{< relref "tutorial-2/index.md">}} if you have questions around graph traversal queries._ 366 367 368 Similarly, let's extend our previous query to fetch the tags of these blog posts. 369 370 ```graphql 371 { 372 authors_and_ratings(func: ge(rating, 4.0)) { 373 uid 374 author_name 375 rating 376 published { 377 title 378 content 379 dislikes 380 tags { 381 tag_name 382 } 383 } 384 } 385 } 386 ``` 387 388 {{% load-img "/images/tutorials/3/m-four-blogs.png" "rating-blog-rating" %}} 389 390 _Note: Author nodes are in blue, blogs posts in green, and tags in pink._ 391 392 We have two authors, four blog posts, and their tags in the result. 393 394 If you take a closer look at the result, there's a blog post with 12 dislikes. 395 396 {{% load-img "/images/tutorials/3/i-dislikes-2.png" "Dislikes" %}} 397 398 Let's filter and fetch only the popular blog posts. 399 Let's query for only those blog posts with fewer than 10 dislikes. 400 401 To achieve that, we need to express the following statement as a query to Dgraph: 402 _Hey, traverse the `published` edge, but only return those blogs with fewer than 10 dislikes_ 403 404 Can we also filter the nodes during traversals? 405 Yes, we can! Let's learn how to do that in our next section. 406 407 ## Filtering traversals 408 409 We can filter the result of traversals by using the `@filter` directive. 410 411 You can use any of the Dgraph's comparator functions with the `@filter` directive. 412 413 You should use the `lt` comparator to filter for only those blog posts with fewer than 10 dislikes. 414 415 Here's the query. 416 417 ```graphql 418 { 419 authors_and_ratings(func: ge(rating, 4.0)) { 420 author_name 421 rating 422 423 publishes @filter(lt(dislikes, 10)) { 424 title 425 likes 426 dislikes 427 tag { 428 tag_name 429 } 430 } 431 } 432 } 433 ``` 434 435 {{% load-img "/images/tutorials/3/j-dislike-index-2.png" "Dislikes" %}} 436 437 Oops! We forgot to add the index for the dislike predicate! 438 439 Go to the Schema tab, find the `dislikes` predicate, add the index from the UI. 440 441 {{% load-img "/images/tutorials/3/g-dislike-index-3.png" "Add index" %}} 442 443 _Note: Notice that the `dislike` predicate is of integer type._ 444 445 Let's rerun the query. 446 447 {{% load-img "/images/tutorials/3/n-three-blogs.png" "rating-blog-rating" %}} 448 449 Now, we only have three blogs in the result. 450 The blog with 12 dislikes is filtered out. 451 452 Notice that the blog posts are associated with a series of tags. 453 454 Let's run the following query and find all the tags in the database. 455 456 ```sh 457 { 458 all_tags(func: has(tag_name)) { 459 tag_name 460 } 461 } 462 ``` 463 464 {{% load-img "/images/tutorials/3/o-tags.png" "tags" %}} 465 466 We got all the tags in the database. 467 My favorite tag is `devrel`. What's yours? 468 469 In our next section, let's find all the blog posts which are tagged `devrel`. 470 471 ## Querying string predicates 472 473 The `tag_name` predicate represents the name of a tag. 474 It is of type `string`. 475 Here are the steps to fetch all blog posts which are tagged `devrel`. 476 477 - Find the root node with the value of `tag_name` predicate set to `devrel`. 478 We can use the `eq` comparator function to do so. 479 - Don't forget to add an index to the `tag_name` predicate before you run the query. 480 - Traverse starting from the node for `devrel` tag along the `tagged` edge. 481 482 483 Let's start by adding an index to the `tag_name` predicate. 484 Go to Ratel, click `tag_name` predicate from the list. 485 486 {{% load-img "/images/tutorials/3/p-string-index-2.png" "string index" %}} 487 488 You can see that there are five choices for indices that can be applied to any `string` predicate. 489 The `fulltext`, `term`, and `trigram` are advanced string indices. 490 We'll discuss them in detail in our next episode. 491 492 There are a few constraints around the use of string type indices and the comparator functions. 493 494 For example, only the `exact` index is compatible with `le`, `ge`,`lt`, and `gt` built-in functions. 495 If you set a string predicate with any other index and run the above comparators, the query fails. 496 497 Although, any of the five string type indices are compatible with the `eq` function. 498 The `hash` index would normally be the most performant to be used with the `eq` comparator. 499 500 501 502 Let's add the `hash` index to the `tag_name` predicate. 503 504 {{% load-img "/images/tutorials/3/m-hash.png" "string index" %}} 505 506 Let's use the `eq` comparator, and fetch the root node with `tag_name` set to `devrel`. 507 508 ```graphql 509 { 510 devrel_tag(func: eq(tag_name,"devrel")) { 511 tag_name 512 } 513 } 514 ``` 515 516 {{% load-img "/images/tutorials/3/q-devrel-2.png" "string index" %}} 517 518 We finally have the node we wanted! 519 520 We know that the `blog post` nodes are connected to their `tag nodes` via the `tagged` edges. 521 522 Do you think that a traversal from the node for `devrel` tag should give us the blog posts? 523 524 Let's try it out! 525 526 527 ```graphql 528 { 529 devrel_tag(func: eq(tag_name,"devrel")) { 530 tag_name 531 tagged { 532 title 533 content 534 } 535 } 536 } 537 ``` 538 539 Looks like the query didn't work! It didn't return us the blog posts! 540 Don't be surprised as this is expected. 541 542 543 Let's observe our Graph model again. 544 545 {{% load-img "/images/tutorials/3/a-main-graph.JPG" "main graph model" %}} 546 547 We know that the edges in Dgraph have directions. 548 You can see that the `tagged` edge points from a `blog post` node to a `tag` node. 549 550 Traversing along the direction of an edge is natural to Dgraph. 551 Hence, you can traverse from any `blog post node` to their `tag node` via the `tagged` edge. 552 553 But to traverse the other way around requires you to move opposite to the direction of the edge. 554 You can still do so by adding a tilde(~) sign in your query. 555 The tilde(~) has to be added at the beginning of the name of the edge to be traversed. 556 557 Let's add the `tilde (~)` at the beginning of the `tagged` edge and initiate a reverse edge traversal. 558 559 ```graphql 560 { 561 devrel_tag(func: eq(tag_name,"devrel")) { 562 tag_name 563 564 ~tagged { 565 title 566 content 567 } 568 } 569 } 570 ``` 571 572 573 {{% load-img "/images/tutorials/3/r-reverse-2.png" "string index" %}} 574 575 We got an error! 576 577 Reverse traversals require an index on their predicate. 578 579 Let's go to Ratel and add the `reverse` index to the edge. 580 581 {{% load-img "/images/tutorials/3/r-reverse-1.png" "string index" %}} 582 583 584 Let's re-run the reverse edge traversal. 585 586 ```graphql 587 { 588 devrel_tag(func: eq(tag_name, "devrel")) { 589 tag_name 590 591 ~tagged { 592 title 593 content 594 } 595 } 596 } 597 ``` 598 599 {{% load-img "/images/tutorials/3/s-devrel-blogs.png" "uid index" %}} 600 601 {{% load-img "/images/tutorials/3/s-devrel-blogs-2.png" "uid index" %}} 602 603 Phew! Now we got all the blog posts that are tagged `devrel`. 604 605 Similarly, you can extend the query to also find the authors of these blog posts. 606 It requires you to reverse traverse the `published` predicate. 607 608 Let's add the reverse index to the `published` edge. 609 610 {{% load-img "/images/tutorials/3/t-reverse-published.png" "uid index" %}} 611 612 Now, let's run the following query. 613 614 ```graphql 615 { 616 devrel_tag(func: eq(tag_name,"devrel")) { 617 tag_name 618 619 ~tagged { 620 title 621 content 622 623 ~published { 624 author_name 625 } 626 } 627 } 628 } 629 ``` 630 631 {{% load-img "/images/tutorials/3/u-author-reverse-1.png" "uid index" %}} 632 633 {{% load-img "/images/tutorials/3/u-author-reverse-2.png" "uid index" %}} 634 635 With our previous query, we just traversed the entire graph in the reverse order. 636 Starting from the tag nodes, we traversed up to the author nodes. 637 638 ## Summary 639 640 In this tutorial, we learned about basic types, indices, filtering, and reverse edge traversals. 641 642 Before we wrap up, here’s a sneak peek into our next tutorial. 643 644 Did you know that Dgraph offers advanced text search capabilities? 645 How about the geo-location querying capabilities? 646 647 Sounds interesting? 648 649 Check out our next tutorial of the getting started series [here]({{< relref "tutorial-4/index.md" >}}). 650 651 ## Need Help 652 653 * Please use [discuss.dgraph.io](https://discuss.dgraph.io) for questions, feature requests and discussions. 654 * Please use [Github Issues](https://github.com/dgraph-io/dgraph/issues) if you encounter bugs or have feature requests. 655 * You can also join our [Slack channel](http://slack.dgraph.io).