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).