<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: fluree</title>
    <description>The latest articles on DEV Community by fluree (@fluree).</description>
    <link>https://dev.to/fluree</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F4008%2F5db637dd-e23a-451b-8929-b5042cbf5b0c.png</url>
      <title>DEV Community: fluree</title>
      <link>https://dev.to/fluree</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fluree"/>
    <language>en</language>
    <item>
      <title>What is SHACL?</title>
      <dc:creator>Fluree Dev</dc:creator>
      <pubDate>Wed, 28 Feb 2024 22:06:00 +0000</pubDate>
      <link>https://dev.to/fluree/what-is-shacl-1li0</link>
      <guid>https://dev.to/fluree/what-is-shacl-1li0</guid>
      <description>&lt;p&gt;&lt;em&gt;SHACL is a critical tool for anyone involved in the management, curation, and utilization of RDF data. Its ability to enforce complex data quality rules in a flexible and scalable manner makes it indispensable for maintaining high-quality, interoperable datasets in the age of big data and the semantic web.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SHACL?
&lt;/h2&gt;

&lt;p&gt;Shapes Constraint Language (SHACL) is a powerful language for validating RDF (Resource Description Framework) knowledge graphs against a set of conditions. These conditions are known as shapes and can be used by data governance professionals to streamline consistent data quality across the organization’s data ecosystem. SHACL was developed by the World Wide Web Consortium (W3C) into the open, industry standard for data quality assurance in data-centric, semantic technologies and linked data projects.&lt;/p&gt;

&lt;p&gt;In Fluree’s graph database, users leverage policy-based SHACL to express constraints like required properties, data types, cardinality, and closed class shapes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the difference between OWL and SHACL?
&lt;/h2&gt;

&lt;p&gt;OWL and SHACL are typically compared as both ways in which to manage and maintain datasets, but their core competencies differ. OWL helps with inference; SHACL helps with validation. Let’s break it down further: &lt;/p&gt;

&lt;p&gt;OWL is primarily designed for defining and reasoning about ontologies. It provides a rich set of constructs for describing the relationships between concepts in a domain, enabling sophisticated inferencing capabilities about the types of entities and their relationships. OWL is used to create complex domain models and to infer new knowledge from existing data.&lt;/p&gt;

&lt;p&gt;SHACL, on the other hand, is focused on data validation. It allows developers and data architects to define constraints on the structure and content of RDF graphs, ensuring that the data adheres to specified patterns, value ranges, or other criteria. While OWL focuses on enabling inference, SHACL is specifically tailored for validation, offering a more direct approach to enforcing data quality rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does SHACL look like?
&lt;/h2&gt;

&lt;p&gt;SHACL uses a graph-based syntax, where shapes are defined as RDF graphs. Let’s take a look at a simple example: let's say that we want to ensure that all values assigned to the property "schema:birthday" are enforced as xsd:dateTime (in plain english: birthdays are formatted as valid dates and times). In Fluree, we could insert our constraint in a ledger like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "@context": "https://ns.flur.ee",
  "ledger": "ledger/data-type",
  "insert": {
    "@id": "ex:UserShape",
    "@type": ["sh:NodeShape"],
    "sh:targetClass": { "@id": "ex:Person" },
    "sh:property": [
      {
        "sh:path": { "@id": "schema:birthDate" },
        "sh:datatype": { "@id": "xsd:dateTime" }
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example defines a shape for &lt;code&gt;ex:Person&lt;/code&gt; instances, ensuring that the ‘birthDate’ property of such entities, if present, must be a valid date-time value. &lt;/p&gt;

&lt;p&gt;What are the benefits of using SHACL for data validation?&lt;br&gt;
Data governance is increasingly becoming critical, as organizations need to leverage clean, available, and trusted data on a day-to-day basis. By employing a global framework for data validation, organizations can save an immense amount of time and effort in standardizing data for analytics and re-use. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Er5tlYL1ZMU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;SHACL offers several benefits for data validation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flexibility and Expressiveness: SHACL can express a wide range of constraints, including property existence, value type, value range, cardinality, and more complex conditions.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability: SHACL validation can be efficiently implemented, making it suitable for large datasets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Standardization: As a W3C standard, SHACL ensures interoperability and consistency across different tools and platforms. This helps make not only the data interoperable, but also the rules that govern data consistency and validation interoperable. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Declarative Approach: SHACL allows the expression of validation rules in a declarative manner, separating the rules from their execution, which can improve maintainability and understandability of data constraints.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What kinds of quality constraints can SHACL enforce?
&lt;/h2&gt;

&lt;p&gt;SHACL can enforce a variety of quality constraints, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structural Constraints: Ensuring that data adheres to a specific schema or model, such as required properties, permissible property values, or specific class hierarchies.&lt;/li&gt;
&lt;li&gt;Value Constraints: Limiting the values that can be taken by properties, including data types, value ranges, and pattern matching.&lt;/li&gt;
&lt;li&gt;Cardinality Constraints: Defining the minimum and maximum occurrences of properties.&lt;/li&gt;
&lt;li&gt;Logical Constraints: Applying logical conditions to properties and values, such as equality or inequality, and combinations thereof through logical operators.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How does SHACL improve enterprise data at scale?
&lt;/h2&gt;

&lt;p&gt;For enterprises dealing with vast amounts of data, maintaining data quality is paramount. SHACL provides a robust framework for ensuring that data across the organization conforms to agreed-upon standards and models. At scale, SHACL helps in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automating Data Validation: Automated tools can leverage SHACL shapes to validate data as it is ingested, updated, or transformed, ensuring continuous data quality without manual intervention.&lt;/li&gt;
&lt;li&gt;Enforcing Data Governance: SHACL shapes can embody data governance policies, ensuring compliance with internal and external data standards and regulations.&lt;/li&gt;
&lt;li&gt;Improving Data Interoperability: By enforcing standardized data models and structures, SHACL facilitates data sharing and interoperability both within the enterprise and with external partners.&lt;/li&gt;
&lt;li&gt;Enhancing Data Quality: Consistent application of SHACL validation helps identify and rectify data quality issues early, reducing errors and improving the reliability of data-driven decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SHACL is a critical tool for anyone involved in the management, curation, and utilization of RDF data. Its ability to enforce complex data quality rules in a flexible and scalable manner makes it indispensable for maintaining high-quality, interoperable datasets in the age of big data and the semantic web.&lt;/p&gt;

&lt;p&gt;Try SHACL out with Fluree! &lt;br&gt;
Head on over to our &lt;a href="https://next.developers.flur.ee/docs/reference/cookbook/#shacl"&gt;cookbook&lt;/a&gt; documentation for some examples that you can test out with your &lt;a href="http://data.flur.ee/signup"&gt;free Fluree cloud account&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>shacl</category>
      <category>rdf</category>
      <category>knowledgegraph</category>
      <category>datavalidation</category>
    </item>
    <item>
      <title>What is JSON-LD?</title>
      <dc:creator>Fluree Dev</dc:creator>
      <pubDate>Tue, 23 Jan 2024 17:33:17 +0000</pubDate>
      <link>https://dev.to/fluree/what-is-json-ld-2dgi</link>
      <guid>https://dev.to/fluree/what-is-json-ld-2dgi</guid>
      <description>&lt;h2&gt;
  
  
  Future-Proof Your Data with JSON-LD
&lt;/h2&gt;

&lt;p&gt;Fluree has officially released native &lt;a href="http://flur.ee/json-ld"&gt;JSON-LD support&lt;/a&gt;. But what exactly is JSON-LD, and why does it matter?  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For developers used to working with document data stores like MongoDB, JSON-LD is a bridge to the world of linked data. Linked data is the reason &lt;a href="https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37430.pdf"&gt;Google has been able to provide such unique and sophisticated services to consumers&lt;/a&gt; --  but that power is about to expand to far more than simple search engine optimization. Linked data allows organizations, people, and applications to access and share distributed sets of knowledge under global semantic standards- a powerful concept in the context of the modern data age.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At Fluree, we are big fans of the semantic web standards - especially RDF - because they allow for &lt;a href="https://flur.ee/2021/03/10/semantic-interoperability-exchanging-data-with-meaning/"&gt;data to be organized and exchanged with universal meaning&lt;/a&gt;. Semantic standards are necessary for a future internet in which machines and humans can seamlessly connect to, leverage, and collaborate around disparate sets of linked data. The implications - especially in the era of emerging AI technologies, enterprise knowledge graphs, and industry data-sharing ecosystems - are profound.&lt;/p&gt;

&lt;p&gt;But we are also realists - in the last ten years, most developers have chosen convenience over the grand vision of the semantic web, opting for JSON document data stores. JSON’s incredibly lightweight interchange format has seen mass adoption thanks in part to the influence of JavaScript on software over the last decade. &lt;/p&gt;

&lt;p&gt;But the simplicity of JSON backfires when it comes to any case of reusing, sharing, or linking data. Without adding the context of data types, classifications, and relationships, data can easily become isolated, leading to a fragmented and siloed understanding of its implications.&lt;/p&gt;

&lt;p&gt;That's why we're passionate about the JSON-LD specification — which Fluree has fully implemented and now supports.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JSON-LD?
&lt;/h2&gt;

&lt;p&gt;JSON-LD -- or JavaScript Object Notation Linked Data -- combines the simplicity and ease of JSON documents with the power of linked data. JSON-LD allows you to encode meaning within your JSON document through the use of a shared vocabulary - a total upgrade from your typical JSON payload. &lt;/p&gt;

&lt;p&gt;JSON-LD is JSON for linked data. In fact, A JSON-LD document is always a valid JSON document. Broadly speaking, there are two core capabilities that the “LD” part provides: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It allows you to embed or reference the definition of objects within your JSON payload. For example, the &lt;a class="mentioned-user" href="https://dev.to/context"&gt;@context&lt;/a&gt; element embedded in a JSON-LD document maps object properties to concepts from an RDF ontology (a universally standardized schema).&lt;/li&gt;
&lt;li&gt;It allows you to assign IRIs to properties in order to establish uniqueness.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔍 What is an IRI?
&lt;/h2&gt;

&lt;p&gt;An IRI (Internationalized Resource Identifier) is a generalization of the more commonly known URI (Uniform Resource Identifier). While URIs are limited to a subset of the ASCII character set, IRIs provide a way to include characters from a wider range, including Unicode. This expansion allows for the use of scripts and characters from various languages around the world, making it more globally inclusive.&lt;/p&gt;

&lt;p&gt;In the context of linked data and the semantic web, IRIs are used to uniquely identify resources. This ensures that there's no ambiguity when referring to particular entities, concepts, or relationships, regardless of where they originate or the language they're represented in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding @ context, @ id and @ type
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;@ context&lt;/strong&gt; - The @ context tag in a JSON-LD payload gives us just that - context - in the form of mapping objects in the document to a vocabulary. For example, one might map @ context to schema.org, a well-known reference site for structured data schemas. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;@ id&lt;/strong&gt; - The @ id tag gives us a way to establish uniqueness for data - which is fundamentally critical to prevent ambiguity and duplication in linked data systems. The @ id tag is sort of like a digital version of an address where we can ‘park’ unique data at URIs and point to them later on. Uniqueness in data allows us to distinguish between things or recognize that one thing in a dataset is the exact same as one thing in another dataset. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;@ type&lt;/strong&gt; - Represents the data type or class of the object, providing a way to categorize the data in terms of what it represents in the real world.&lt;/p&gt;

&lt;p&gt;Let’s take a look at a JSON-LD document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "@context": {
    "schema": "https://schema.org/",
    "name": "schema:name",
    "author": "schema:author",
    "datePublished": "schema:datePublished",
    "articleBody": "schema:articleBody"
  },
  "@type": "schema:Article",
  "@id": "https://example.com/articles/json-ld-introduction",
  "name": "Introduction to JSON-LD",
  "author": {
    "@type": "schema:Person",
    "name": "John Doe"
  },
  "datePublished": "2023-10-27",
  "articleBody": "JSON-LD is a powerful way to represent linked data using JSON. It combines the simplicity of JSON with the capabilities of linked data, allowing for richer metadata, better SEO, and improved data interoperability..."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;@ context: This defines the context of the JSON-LD document. It maps terms to IRIs so that properties such as "name" or "author" are clearly associated with concepts defined at "schema.org", a popular vocabulary for structured data on the internet.&lt;/li&gt;
&lt;li&gt;@ type: Specifies that this JSON-LD document represents an article. The "schema:Article" IRI defines this as an article type as per the schema.org vocabulary.&lt;/li&gt;
&lt;li&gt;@ id: Provides a unique identifier for this article. In this case, it's a URL to the article on "example.com".&lt;/li&gt;
&lt;li&gt;author: Contains information about the author of the article. Nested within it, we see another @type that specifies this entity as a "Person" as per the schema.org vocabulary. The author has a "name" property.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why use JSON-LD?
&lt;/h2&gt;

&lt;p&gt;JSON-LD gives developers a familiar format in which to deliver the value of linked data and provides organizations with an easy path to integrate the benefits of linked data into a broader range of their data management operations.&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/watch?si=HHGZaenyqCayFjBU&amp;amp;%3Bt=538&amp;amp;v=vlb61pnI9KM&amp;amp;feature=youtu.be" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--JFrD676g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/vlb61pnI9KM/maxresdefault.jpg" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/watch?si=HHGZaenyqCayFjBU&amp;amp;%3Bt=538&amp;amp;v=vlb61pnI9KM&amp;amp;feature=youtu.be" rel="noopener noreferrer" class="c-link"&gt;
          Webinar | Getting Started with Fluree V3 - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Are you ready for Fluree Version 3? With an intuitive cloud-based managed service option and full JSON-LD support, we are excited to walk through our product...
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--DhFoJ1Lp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.youtube.com/s/desktop/d84e1538/img/favicon.ico" width="16" height="16"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;What’s the deal with Linked Data? Linked data is the practice of connecting data across domains through the use of semantic standards. Linked data uses standardized schemas known as ontologies to transform information into organized, connected, and contextual knowledge. These properties allow data to become interlinked and machine-readable on the web and promote knowledge discovery and federated analytics. Linked data can be applied within the enterprise in the form of semantic knowledge graphs, on the public internet in the form of Open Linked Data, or in a hybrid model in the form of semantic data-sharing ecosystems.&lt;/p&gt;

&lt;p&gt;JSON-LD allows organizations to gain all the benefits of linked data - without the hassle and overhead of transforming data or forcing developers to use a foreign data format. JSON-LD immediately increases the value of JSON documents by making the data stored within them interoperable with other linked data systems - such as internal knowledge graphs or on the open linked web - as well as by providing an accessible medium for developers and applications to interact with linked data. &lt;/p&gt;

&lt;p&gt;Here’s a few examples of how JSON-LD makes an impact: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Building Data-Centric Applications&lt;/strong&gt; - Software increasingly produces data that has more than one purpose - whether analytics, sharing, compliance reporting, or re-operationalization into a new application - data is versatile. JSON-LD future-proofs data for reuse within a data-centric architecture, allowing data to exist independently of a singular application and to power multiple data applications without duplication. &lt;a href="https://flur.ee/2020/10/05/introduction-to-data-centricity/"&gt;Read more about data-centricity here&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Participation in the Semantic Web&lt;/strong&gt; - JSON-LD gives document data a path towards participation in the semantic web. This core initial use case has seen wide adoption in the SEO (Search Engine Optimization) field because JSON-LD helps add metadata and structure to webpages. Beyond SEO, JSON data will need to interoperate at webscale for a variety of use cases - and JSON-LD is the perfect tool for the job.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Broadening the Impact and Capabilities of Enterprise Knowledge Graphs&lt;/strong&gt;: Linking data allows the formation of ontology-driven knowledge graphs, a data management trend that supports advanced analytics and insights through the use of semantic data standards. JSON-LD allows knowledge graphs to incorporate semantically tagged documents as part of their data domains - but it also provides a medium in which to operationalize applications atop knowledge graphs.&lt;br&gt;
Knowledge graphs should be dynamic and operational in that they power multiple data applications and are contributed to by multiple data source domains. This is supported by our &lt;a href="https://flur.ee/2020/10/05/introduction-to-data-centricity/#:~:text=The%20Data%2DCentric%20Architecture%20treats,the%20entire%20data%20value%20chain."&gt;data-centric philosophy&lt;/a&gt; in which data should be able to connect to, influence and power multiple data applications. Because JSON-LD extends JSON with linked data capabilities, adding and deleting objects in knowledge graphs is as simple as performing transactions against a document database like MongoDB. This read/write capability then allows a knowledge graph to serve as an operational backend to real-time web-based applications that use a JSON interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feeding Analytics Better Data&lt;/strong&gt; - JSON-LD extends the value and versatility of data with context, thereby preparing it for downstream activity. For instance, JSON-LD prepares data (that would otherwise be too simple or obscure) for an instantaneous analytical experience within data science teams. Because JSON-LD data arrives with self-describing context and a standardized semantic schema, downstream systems can immediately understand, evaluate, and take action on insights. For these systems, JSON-LD makes data immediately &lt;a href="https://flur.ee/2020/07/08/making-data-fair/"&gt;F.A.I.R. (Findable, Accessible, Interoperable and Reusable)&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Machine-readability&lt;/strong&gt; - JSON-LD upgrades JSON documents to become machine-readable, meaning computers can automatically exchange, access and understand information without the need for a human intermediary. This capability will be crucial for data to participate in the machine-to-machine web and power the next wave of automation and AI. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data sharing ecosystems&lt;/strong&gt; - Data sharing ecosystems are on the rise, introducing complexities that data systems have not had to account for in the past. For example, data from a single repository might be contributed to by multiple organizations. Or, records in a consortium might need to flow across systems and applications - in a hospital system, for example, patient information is securely collaborated on by different clinics and insurance providers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Linked data supports these complexities&lt;/strong&gt; - with semantic standards, we can exchange information across systems, execute federate queries across multiple disparate data sets, and collaborate around data sets with standardized schemas. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verifiable Credentials &amp;amp; Decentralized Semantics&lt;/strong&gt; - Allows for authentication and assurance of the data's source, ensuring its validity and credibility. By incorporating decentralized semantics, data gets rooted in a universally accepted framework, making it trustworthy and interoperable across a network. (check out our cool work with the &lt;a href="https://www.youtube.com/watch?v=XZUZSlsAepg"&gt;Trusted Learner Network!&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;At Fluree, our vision of the Web3.0 involves an internet of trusted and linked data. The problem is that our tools haven’t addressed the need for data to be linked - developers have found document databases quite preferable for simplicity’s sake. It’s time to prepare our data -- at the source of its creation -- with capabilities for interoperability and exchange across disparate data systems. JSON-LD is that needed bridge. Try JSON-LD out for yourself &lt;a href="http://dev.flur.ee"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;There are emerging innovations for trusted and interoperable data exchange that JSON-LD will help fuel - including personal knowledge graphs and &lt;a href="https://www.w3.org/TR/vc-data-model/"&gt;verifiable credentials&lt;/a&gt;. We’ll cover examples of those specifications in future blog posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://json-ld.org/"&gt;(https://json-ld.org/)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://flur.ee/json-ld/"&gt;(https://flur.ee/json-ld/)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.slideshare.net/gkellogg1/json-for-linked-data"&gt;(https://www.slideshare.net/gkellogg1/json-for-linked-data )&lt;/a&gt;&lt;/p&gt;

</description>
      <category>json</category>
      <category>linkeddata</category>
      <category>database</category>
      <category>web3</category>
    </item>
    <item>
      <title>Seamless Data Sharing, Baked Right In</title>
      <dc:creator>Fluree Dev</dc:creator>
      <pubDate>Thu, 21 Dec 2023 20:25:39 +0000</pubDate>
      <link>https://dev.to/fluree/seamless-data-sharing-baked-right-in-5bji</link>
      <guid>https://dev.to/fluree/seamless-data-sharing-baked-right-in-5bji</guid>
      <description>&lt;p&gt;&lt;em&gt;Explore fundamental principles, uncover challenges, and discover how Fluree's open web standards effortlessly facilitate sharing data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As things start to wind down at the end of the year, those of us in tech start looking for easy wins, like updating our email signatures to match the new company branding guidelines or scheduling a “first thing next year” check-in for that data integration effort that has as much chance of reporting progress as Santa’s milk and cookies have seeing Christmas Day.&lt;/p&gt;

&lt;p&gt;We who manage data and share it with others knowingly smile because we’ve all seen a “data integration” project or even a “simple data request” that seems straightforward but is actually fraught with unforeseen challenges and setbacks. Why is it that these kinds of efforts are so widely known to cause grief? It’s because in a career that’s so often filled with miraculous technological advances and software tools that exponentially narrow development time and widen the impact of our efforts, we feel ridiculous estimating (and inevitably extending) a timeline of half a year or more for any project that involves sharing existing data across applications and firewalls. &lt;/p&gt;

&lt;p&gt;Let’s get into the fundamentals of sharing data, expose the challenges lurking in the implementation details, and learn why projects that use Fluree need not be concerned about any of this thanks to a few open web standards – baked right into Fluree – that enable seamless data sharing.&lt;/p&gt;

&lt;p&gt;The chestnut of this article came from our &lt;a href="https://developers.flur.ee/docs/examples/datasets/academic-credentials/querying/"&gt;walkthrough documentation on the fictional Academic Credential Dataset&lt;/a&gt;. If you’d like to dive deeper into solving the issues tackled in this post, head on over to our &lt;a href="https://developers.flur.ee/"&gt;docs site&lt;/a&gt; to see what it’s like solving hard problems with Fluree.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Data Sharing Problem
&lt;/h2&gt;

&lt;p&gt;In our fantastic doc &lt;a href="https://developers.flur.ee/docs/learn/tutorial/collaborative-data/"&gt;Collaborative Data&lt;/a&gt; we highlight the core problem with sharing data: &lt;a href="https://martinfowler.com/bliki/TwoHardThings.html"&gt;naming&lt;/a&gt;! Because you and I describe the same things in different ways – my Customers table and your CustomerDetails table might both describe Freddy the Yeti and may even contain the same exact data for Freddy, but in typical database systems, there is no way for us to know we’re describing the same yeti, nor can we even compare the data we have on Freddy from our separate systems without a mapping definition and process. &lt;/p&gt;

&lt;p&gt;In fact, when there are any discrepancies between the source and destination schemas, the task of sharing data shifts from a self-service and, dare I say, automated task to a more complex endeavor that requires business analysts, developers, database administrators, and, of course, project managers to corral the whole circus of defining, communicating, building, and validating the necessary data pipeline. I may be exaggerating a bit, especially for smaller requests where a simple export of a small set of records is concerned, but even for a small task, some understanding of the target data and context is required by the provider and consumer to make sense of the request and resulting data. Note that in the case of building a data pipeline, much of the burden is put on the shoulders of tech knowledge workers where we’re expected to learn and reason about multiple contexts and construct systems integrations that must communicate over time and space and handle edge cases and dirty data and will eventually be asked to shoulder the weight of maintenance and changes of requirements and feature creep. This is where the cost and grief comes from. &lt;/p&gt;

&lt;p&gt;If maintaining a consistent mapping is crucial for the data owner, it can be achieved by layering it in as the source data is added. However, this approach often results in data duplication, as the information must be stored in multiple formats. Alternatively, the mapping can be automated and done on-the-fly, as the data is requested, but this takes development resources and, depending on the amount of data and frequency of requests, can get expensive (and deeply annoying). Neither of these methods takes into account scenarios where mappings evolve over time or when there are numerous requestors, each with their unique data format requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WHOO_6_X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lgzmznzpytr1x1sbphl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WHOO_6_X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lgzmznzpytr1x1sbphl.png" alt="Image description" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay so differing data schemas mean trouble for data sharing, making it complex, expensive and generally slow. So why do we have these differences in the first place? If it's such an effort to map and transform data, why can't the receiver just use the same schema as the sender? Or vice versa?&lt;/p&gt;

&lt;p&gt;There are many reasons that vary with size and scale, but most of them boil down to communication, coordination, and cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different Goals, Different Contexts
&lt;/h2&gt;

&lt;p&gt;When building data exports, APIs, and other data sharing infrastructure, data owners lean on their own internal understandings of their data. There are intrinsic properties of the data (e.g. relationships, data types, field names) that only exist as a byproduct of the context in which the data owner collected and generated the data, and yet these properties dictate the format, shape, and content of the data being shared. On the other hand, each and every data consumer (those that receive data from data owners) have another distinct understanding of the data they're interested in. They operate within a different context. They have applications and analytics that are built on data of a certain shape with certain properties that have certain names and types.&lt;/p&gt;

&lt;p&gt;Efficiently conveying these distinct contexts and ensuring that everyone consistently employs the same data context for their specific use cases can appear to be an insurmountable challenge. On the other hand, if we permit each consumer to maintain their own context, any modification to the data sharing infrastructure necessitates an equivalent degree of communication and coordination, resulting in each individual bearing the cost of staying up-to-date.&lt;/p&gt;

&lt;p&gt;The challenges with data formatting and mapping make sharing data and hosting data sources difficult to accomplish and, when successful, constrained to niche, data-intensive research fields that require a consistent context. To mitigate, these problem spaces must rely on centralized data brokers that dictate the sharing format and other rules of engagement. This setup means relinquishing data ownership and control, reduced benefit of data partnerships, and the limited reach of knowledge and information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tl;dr is: the current state of data infrastructure can only produce data silos which constrain the impact of our data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In an ideal world, we would all use the same schema, the same data context. We would use the same table names, use the same column names and data types, and, while we’re dreaming, we’d use the same identifiers for our records! That way, there’s no need for a translation layer, there’s just retrieving data. Seems silly right? There’s no way we can all use the same database schema. What would that even mean?&lt;/p&gt;

&lt;p&gt;Fluree builds on web standards to provide essential features that, when combined, solve these traditionally challenging problems. One of these standards is the JSON-LD format, which gives our data the ability to describe itself enabling portability beyond the infrastructure where it originated. We call this “schema on write" and “schema on read,” which just means developers can build their databases on top of universal standards, and that data can be immediately shared, pre-packaged with mappings and context for consumer use cases. Let’s take a closer look at how Fluree’s approach to data management obviates these problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Data Sharing Solution
&lt;/h2&gt;

&lt;p&gt;What does it mean for our data to be able to "describe itself" and how does this concept solve these longstanding data-sharing problems? I mentioned the term "context" a bit in my statement of the problem. In a nutshell, the data context contains all of the semantic meaning of the data. This includes field names, relationships among objects and concepts, type information like is this data a number, a date, or a more complex class like an invoice or a patient visit. This contextual data is traditionally defined all over the place: in table and column definitions, in application and API layers, in data dictionaries distributed with static datasets, in notes columns in a spreadsheet, in the head of the overworked and under-resourced data architect. This contextual data, as discussed, can be difficult to maintain, represent, and transfer to data consumers.&lt;/p&gt;

&lt;p&gt;But wait! What if all this data was stored and retrieved as data in the dataset? What would it look like if we took all of the contextual data that can be found in the best, most-complete data dictionary, API documentation, or SQL schema explorer and just inject it right in there with the data content itself? JSON-LD and a few other open web standards, like RDF and RDFS, do this exactly and Fluree relies on them to enable simple and seamless data sharing.&lt;/p&gt;

&lt;p&gt;RDF and JSON-LD are simply data formats that can represent graph data. We go into more detail in our &lt;a href="https://developers.flur.ee/docs/learn/tutorial/fluree-data-model/"&gt;Data Model&lt;/a&gt; doc and there are some excellent resources online as RDF has been around for a bit. RDFS is an extension of RDF that adds some very useful data modeling concepts like classes and subclasses, which enables us to describe the hierarchies in our data. JSON-LD and its ability to convey contextual and vocabulary data alongside the data itself is talked about extensively in our excellent &lt;a href="https://developers.flur.ee/docs/learn/tutorial/collaborative-data/"&gt;Collaborative Data&lt;/a&gt; doc. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gist is that by using universally defined identifiers for both subjects and properties, all participants (both data sources and consumers) can build on top of a fully-defined and open understanding of the data schema. No more data silos.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh hey! Thanks for reading! I’ll leave you with another benefit of using Fluree: portability! Portability, the opposite of “vendor lock in”, is another one of Fluree’s incredible side effects. Because Fluree is built on open standards, like the ones discussed in this article, all of the value provided is baked right into the data itself! This means that Fluree is relying on externally-defined mechanisms (including the storage format, RDF) that have meaning outside of any Fluree database or platform. So when sharing your data or if you decide to use a different database in the future, all of the self-describability goes along for the ride! &lt;/p&gt;

&lt;p&gt;Blog credits to Fluree Developer Jack White&lt;/p&gt;

</description>
      <category>database</category>
      <category>web3</category>
      <category>architecture</category>
      <category>development</category>
    </item>
    <item>
      <title>Fluree is moving to Discord</title>
      <dc:creator>Trey Botard</dc:creator>
      <pubDate>Tue, 04 Jan 2022 01:06:44 +0000</pubDate>
      <link>https://dev.to/fluree/fluree-is-moving-to-discord-3pdh</link>
      <guid>https://dev.to/fluree/fluree-is-moving-to-discord-3pdh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The Fluree community has seen substantial growth over the last year.&lt;br&gt;
With the velocity of growth and the big goals we have for the community,&lt;br&gt;
we need a new home.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Discord has become an ever-present tool for communication on the web. The Fluree community has been on Slack for the past several years and for the most part we have been satisfied by the platform. However, over the past year, we've seen significant growth and as we've grown, we've begun to run up against some of the shortcomings of Slack as a platform for an open community. As we imagined where we want to take the Fluree community going forward, it became harder and harder to see how we could modify our vision to fit within the bounds of Slack. We needed a new platform for our community. After investigating the alternatives, we found Discord to be an extremely attractive option with all of the benefits provided by Slack and a ton of new functionality to boot. We did some preliminary internal testing, then tested the waters with a couple weeks of beta testing (shout out to our Beta testers!) and found the experience to be even better than we had hoped.&lt;/p&gt;

&lt;p&gt;So, we made the exciting decision to migrate our community on over.&lt;/p&gt;



&lt;h2&gt;
  
  
  Why Migrate?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  No message limits
&lt;/h3&gt;

&lt;p&gt;The primary limitation in Slack is the message limits. If you weren't aware, Slack only allows up to 10,000 messages per workspace. There are over 700 members in the public Fluree Slack and the amount of chat happening meant that we were only able to see messages within about a 6-month window. As our community grows, that window will only shrink and the knowledge shared within this space will be lost at an accelerated pace. Discord has no message limit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice chat and screen share
&lt;/h3&gt;

&lt;p&gt;Another big point of differentiation between the two platforms is the availability of voice chat and screen sharing. Discord has a ton of features around this which we will begin to take full advantage of. We want to enable our members to self-organize and work on things together using the Fluree Discord as needed. This will enable just that. Not to mention the functionality the Fluree team can use to host events and activities from with Discord. (We have some fun stuff planned for this year!)&lt;/p&gt;

&lt;h3&gt;
  
  
  Open by default
&lt;/h3&gt;

&lt;p&gt;Another issue with Slack for an open community is the way channels are structured. Channels are hidden by default and require a member to be invited or actively search for new channels to join. This is not the way Discord is set up. All channels are public by default, which creates an easy path to exploration and cross-pollination, with good tooling for a user to manage notifications per channel or category as desired. We think this is better for an open community and are excited for this change in structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better moderation tooling
&lt;/h3&gt;

&lt;p&gt;Fortunately, this hasn't been an issue thus far, but moderation is a &lt;em&gt;vital&lt;/em&gt; part of community management. Creating a safe space for all of our community members is extremely important to the Fluree team and frankly the tooling for moderation in Slack is practically non-existent. Discord provides functionality which will enable us to create the spaces we want and ensure a welcoming, helpful, and safe environment for all who choose to join us.&lt;/p&gt;



&lt;h2&gt;
  
  
  Timeline
&lt;/h2&gt;

&lt;p&gt;Here's the plan for the migration: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Thurs. Jan 6th&lt;/em&gt;: Open Discord server to the public.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Mon. Jan 10th&lt;/em&gt;, and &lt;em&gt;Fri. Jan 14&lt;/em&gt;: Fluree DevRel team will be available for questions in the Discord to assist with the new tool.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Mon. Jan. 31st&lt;/em&gt;: Close public Slack channels to new comments. Begin migrating private channels to shared channels where needed. 

&lt;ul&gt;
&lt;li&gt;We will migrate private support channels to shared Slack channels from our internal Slack workspace. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Thurs. Feb 3rd&lt;/em&gt;: February Office Hours to be held in the new Discord server!!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Of course, the team will be available for any questions in both Discord and Slack for the duration of the migration and are more than happy to assist where needed. &lt;/p&gt;




&lt;p&gt;We are extremely excited for this new chapter of the Fluree community. There will be bumps in the road as we migrate such a large community, but we are confident this is the right choice, both for the long term health of the Fluree community and for Fluree itself.&lt;br&gt;
Keep an eye on our &lt;a href="https://twitter.com/flureepbc"&gt;Twitter&lt;/a&gt; in the coming weeks for an invite link to the new Discord server. If you're in the Fluree Slack, we'll&lt;br&gt;
be making an announcement there as well.&lt;/p&gt;

&lt;p&gt;We look forward to seeing you in the new Fluree Discord!&lt;/p&gt;

</description>
      <category>fluree</category>
      <category>discord</category>
      <category>community</category>
    </item>
    <item>
      <title>Fluree in Docker - A Single Instance</title>
      <dc:creator>Trey Botard</dc:creator>
      <pubDate>Thu, 07 Oct 2021 21:25:12 +0000</pubDate>
      <link>https://dev.to/fluree/fluree-in-docker-a-single-instance-15i8</link>
      <guid>https://dev.to/fluree/fluree-in-docker-a-single-instance-15i8</guid>
      <description>&lt;p&gt;Managing dependencies is a pain in the tuchus. Whether in the cloud, in a private data center, or just on your laptop, ensuring that you have the correct version of Java or Node or whatever other runtime works properly with both the application and the OS and all of the other dependencies can quickly turn into a nightmare. Docker solves this by bundling all of the dependencies together in a single image such that as long as the Docker runtime is deployed on the target infra, your app should function as desired. No muss, no fuss. 🥳&lt;/p&gt;

&lt;p&gt;Let's walk through the set up necessary to get your Fluree backend up and running. (Deployment to a public cloud will be out of scope for this post). This will be the first of a 3 part series on working with Fluree in Docker. The next one will be about setting up a Transactor Group!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To begin with, you will need to have Docker on your machine. Please visit the &lt;a href="https://www.docker.com/get-started"&gt;Docker Getting Started Docs&lt;/a&gt; to get it set up, if you don't have it configured already.&lt;br&gt;
Once Docker is installed and running you will need to grab the &lt;a href="https://hub.docker.com/r/fluree/ledger"&gt;Fluree ledger image&lt;/a&gt; from DockerHub. The &lt;a href="https://docs.docker.com/engine/reference/run/"&gt;Docker CLI&lt;/a&gt; is a great tool for managing images on your machine. We will use the &lt;code&gt;docker pull&lt;/code&gt; command to grab the fluree/ledger image. Open a terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;docker pull fluree/ledger:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of writing, this will pull the 1.0.0 beta 15 ledger image from Docker Hub, which is the most up-to-date version of Fluree. Once the Fluree ledger 1.0.0 is released, beta releases will go under their own tag. At any time, you can pull a specific release, if that is needed. You would simply define the image to pull using the tag like this: &lt;code&gt;fluree/ledger:1.0.0-beta14&lt;/code&gt;.&lt;br&gt;
You can see all of the release tags for Fluree in our &lt;a href="https://github.com/fluree/ledger/tags"&gt;Github Repo&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Set up and run the container
&lt;/h2&gt;

&lt;p&gt;Ok, you have the image, now what?&lt;br&gt;
There are a couple of parameters which Fluree needs in order to start up correctly.&lt;br&gt;
These can be passed in when starting the container using the &lt;code&gt;docker run&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;You can simply start the image by calling &lt;code&gt;docker run fluree/ledger&lt;/code&gt;, but this will not expose the ports you will need to have in order to use the HTTP endpoints. Internally, Fluree listens on port 8090 for the HTTP calls, so this port will need to be mapped to an exposed, public port on the container. This can be done with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -p 8090:8090 fluree/ledger
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ports correspond to ExternalPort:InternalPort. So, if you have 2 containers running, you will need to map the first of the two to a different port and leave the second number as-is because that is the port which Fluree is listening on. So for your second container, you would pass &lt;code&gt;-p 8091:8090&lt;/code&gt; or some other port number of your choosing.&lt;br&gt;
This spins up Fluree inside of your container, you will see the default configs print to the terminal and some messages about the consensus and state of the server. You can see the container and some metadata by running &lt;code&gt;docker ps&lt;/code&gt; in another terminal.&lt;/p&gt;
&lt;h3&gt;
  
  
  Naming your Container
&lt;/h3&gt;

&lt;p&gt;By default, Docker will assign your container both a CONTAINER_ID and a NAME, which you can see via the &lt;code&gt;docker ps&lt;/code&gt; command or in the Docker Desktop UI. The name will be 2 randomly assigned words, but you can name your container when you initialize it with the &lt;code&gt;docker run&lt;/code&gt; command. This is useful because you can then use that name to restart your container, if you stop it for whatever reason. (At this point stopping the container will lose any data, but in a bit, we will connect the container's file system to a local directoy for data persistence 🙌). You can do this by adding the &lt;code&gt;--name&lt;/code&gt; flag to the &lt;code&gt;run&lt;/code&gt; command, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -p 8090:8090 --name ledger1 fluree/ledger
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when you run &lt;code&gt;docker ps&lt;/code&gt;, the NAMES field will be &lt;code&gt;ledger1&lt;/code&gt; instead of a randomized pair of words.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One caveat to using the &lt;code&gt;--name&lt;/code&gt; flag is that if you stop your container or kill the terminal, that name will still be associated with that container. So you may need to run &lt;code&gt;docker rm ledger1&lt;/code&gt; to remove the container, if you want to &lt;code&gt;docker run&lt;/code&gt; with the name ledger1 again. (This applies to the randomly-assigned container names as well. They will exist on the machine until they are removed.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Interacting with your Instance
&lt;/h2&gt;

&lt;p&gt;Now that your ledger is up and running on your machine, there are a few ways for you to interact with the ledger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Admin UI
&lt;/h3&gt;

&lt;p&gt;Every instance of Fluree contains a small utility for working with the ledgers, called the AdminUI. This is a browser based UI maintained by the Fluree team for working with instances of Fluree, whether as a single instance or in a transactor group. Once you have your Fluree instance ready with the HTTP port exposed, you can start the Admin UI by going to &lt;code&gt;http://localhost:[EXPOSED PORT]&lt;/code&gt; in your browser.&lt;br&gt;
If you used the command above to start up your instance, use 8090 for the &lt;code&gt;[EXPOSED PORT]&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We have a &lt;a href="https://youtube.com/c/fluree"&gt;YouTube&lt;/a&gt; video walkthrough of the AdminUI coming soon.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  HTTP Calls
&lt;/h3&gt;

&lt;p&gt;Fluree also contains an HTTP client which exposes several &lt;a href="https://docs.flur.ee/api/1.0.0/downloaded-endpoints/downloaded-examples"&gt;HTTP endpoints&lt;/a&gt; for programmatically working with Fluree. Any of these endpoints can be hit by calling &lt;a href="http://localhost:8090/fdb/%5Bendpoint%5D"&gt;http://localhost:8090/fdb/[endpoint]&lt;/a&gt; or if the endpoint is ledger specific &lt;a href="http://localhost:8090/fdb/%5Bnetwork%5D/%5Bdb%5D%5Bendpoint%5D"&gt;http://localhost:8090/fdb/[network]/[db][endpoint]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At startup, there are no dbs on your instance, so it is recommended to start by using the &lt;a href="https://docs.flur.ee/api/1.0.0/downloaded-endpoints/downloaded-examples#new-db"&gt;/new-db&lt;/a&gt; endpoint first.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a Persistent Volume
&lt;/h2&gt;

&lt;p&gt;Fluree is a ledger and database. Both of these things require persisting data, which Docker does by default, but we'll want to configure it ourselves. To do that, we will need to do what is called mounting a volume to the container. This volume will live on after the container is spun down or goes offline for some reason in the place where we told it to be.&lt;/p&gt;

&lt;p&gt;Fluree already has a mechanism for writing to a file system. In fact, there is a customizable parameter which enables you to specify the path in the file system where you would like Fluree to write its data. You can see all of the &lt;a href="https://docs.flur.ee/docs/1.0.0/getting-started/fluree-anywhere#config-options"&gt;configuration options&lt;/a&gt; in the docs. The config we are interested in now is &lt;code&gt;fdb-storage-file-directory&lt;/code&gt;. By default, this is set to &lt;code&gt;/var/lib/fluree&lt;/code&gt; whether Fluree is being run in a container or in a JVM directly on a server. This means we can use some functionality in the Docker CLI to bind a directory in our local filesystem to this directory &lt;em&gt;inside&lt;/em&gt; the container. Docker run has a flag called --volume (aliased to -v) where you can specify the two directories to be bound together. It will look like this &lt;code&gt;-v "[local/path/to/dir]:[container/path/to/dir]"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For my example, I will tell my container to bind to &lt;code&gt;Users/treybotard/Projects/fluree-data/docker-blog/&lt;/code&gt;. To put this together with the &lt;code&gt;run&lt;/code&gt; command from above; your command should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -p 8090:8090 -v "/Users/treybotard/Projects/fluree-data/docker-blog/:/var/lib/fluree" fluree/ledger
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that I've run this command, I can open up the AdminUI, add a new ledger to my Fluree instance, and when I path to my docker-blog folder, I will see 2 folders, &lt;code&gt;group/&lt;/code&gt; and &lt;code&gt;ledger/&lt;/code&gt;. These are the folders Fluree uses to maintain raft logs (in &lt;code&gt;group/&lt;/code&gt;) and the encrypted indexes (in &lt;code&gt;ledger/&lt;/code&gt;). I'm not going to go into too much detail here about this structure. If you are interested in reading more about how Fluree maintains the &lt;a href="https://docs.flur.ee/guides/1.0.0/architecture/indexes"&gt;indexes&lt;/a&gt; or how Fluree interacts with the &lt;a href="https://docs.flur.ee/guides/1.0.0/infrastructure/file-system"&gt;file system&lt;/a&gt; you can read more in the docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Private key file
&lt;/h3&gt;

&lt;p&gt;When using the &lt;code&gt;--volume&lt;/code&gt; command to persist your data outside of the container, if a private key is not provided on start-up, Fluree will create a default private key. This key (whether provided or generated at startup) is used for a few access controls in developement mode. What this means is that if you want to reuse the same identity to access the persisted data, you will need to store your key outside of the container and pass it in when spinning up a fresh container. This can be done a few different ways, but for simplicity's sake, we'll just look at passing the private key into the container as an environment variable with &lt;code&gt;-e&lt;/code&gt;. Using an environment variable requires passing in &lt;code&gt;-e FDB_GROUP_PRIVATE_KEY=[PRIVATE_KEY]&lt;/code&gt; when starting the container.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now our command looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -p 8090:8090 -v "/Users/treybotard/Projects/fluree-data/Docker-blog/:/var/lib/fluree" --name ledger1 -e FDB_GROUP_PRIVATE_KEY=123456789 fluree/ledger:latest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Docker start and stop
&lt;/h2&gt;

&lt;p&gt;One very convenient way to maintain my development environment is to use the &lt;code&gt;--name&lt;/code&gt; flag on a container with a volume mounted on it. What this enables is the &lt;code&gt;stop&lt;/code&gt; and &lt;code&gt;start&lt;/code&gt; functionality in the Docker CLI. If i have a container specifically for a client project or a demo I am working on, I give it a meaningful name "docker-blog" and mount it to a volume stored next to the source code where I am working. I can then conveniently run &lt;code&gt;docker start docker-blog&lt;/code&gt; when I am ready to work on the container. It knows which ports to use and can spin up the container exactly the way it was when I ran &lt;code&gt;docker stop docker-blog&lt;/code&gt; when I stopped working on it before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Convenience Commands and Flags
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--rm&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you are just testing out some some ledgers and are making some throw-away ledgers, I recommend adding the &lt;code&gt;--rm&lt;/code&gt; flag. Going to spin up a named container which you forgot to spin down, but getting an error that the container name already exists gets old quickly. This will remove the container when you either CTRL+C or send SIGINT to the container some other way.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;-d&lt;/code&gt; and &lt;code&gt;attach&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you have been spun up a Fluree container before, you will have seen that the output is relatively chatty. One easy way to not have to see that in your terminal is to pass the &lt;code&gt;-d&lt;/code&gt; flag when starting up the container. This will run Fluree in a detached process and not print to the console. You can run &lt;code&gt;docker attach [container name]&lt;/code&gt; to reattach to the console and see the logs in your terminal. If you didn't give the container a name, you can look it up with &lt;code&gt;docker ps -a&lt;/code&gt; to see all the containers, including the ones which are stopped.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;docker exec&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Sometimes, it can be very useful to have a bash terminal inside a running container &lt;em&gt;while Fluree is running&lt;/em&gt;. You can use the &lt;code&gt;docker exec&lt;/code&gt; command to run a command inside a running container. One useful way which I use this is to run &lt;code&gt;docker exec -it [container name] /bin/bash&lt;/code&gt;. This opens a bash terminal in the working directory of my container where Fluree is running.&lt;/p&gt;

&lt;p&gt;It can also be useful to access the file system in a container with Fluree inside it, even when Fluree is not running. To startup a container without initializing Fluree, you need to use &lt;code&gt;docker run&lt;/code&gt;, but override the &lt;code&gt;--entrypoint&lt;/code&gt;. That looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -it --entrypoint=bash fluree/ledger
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start up a container and give you a bash terminal with which to explore.&lt;/p&gt;

&lt;p&gt;With these commands, a large percentage of the functionality needed to work with Fluree locally can be achieved. Next week, we'll take a look at how to set up a Transactor Group (several Fluree instances networked together) in Docker using similar commands &lt;em&gt;and&lt;/em&gt; Docker compose!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>fluree</category>
      <category>blockchain</category>
      <category>database</category>
    </item>
    <item>
      <title>Time traveling with Fluree</title>
      <dc:creator>Trey Botard</dc:creator>
      <pubDate>Thu, 01 Jul 2021 18:18:35 +0000</pubDate>
      <link>https://dev.to/fluree/time-traveling-with-fluree-30nj</link>
      <guid>https://dev.to/fluree/time-traveling-with-fluree-30nj</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7f1ejj4frbx4h3u13ifo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7f1ejj4frbx4h3u13ifo.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;When you get down to it, if you are building an app with Fluree as the backend, it is simplest to think of Fluree as a database. This can be a useful way to think about working with Fluree, but by doing so there is a lot being left on the table. The unique combination of technologies which make Fluree what it is enable some extremely powerful functionality and unlock ways of working with data which are either uncommon or simply not possible with other data stores. Let's talk about what some of those are, how to use them, and what this type of functionality could enable in your Fluree-backed application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;In addition to a graph database for querying data, Fluree is built with an immutable ledger as the backbone which holds the dataset. This part of Fluree is what enables some really interesting and particularly unique functionality. 'Immutable ledger' is one of those terms which I had to Google in order to understand when I started at Fluree, so let's break that down a bit.&lt;/p&gt;

&lt;p&gt;Fluree associates related data elements, called subjects. Each subject has an &lt;code&gt;_id&lt;/code&gt; which is used to correlate the attributes (called predicates) and the values of those predicates together to form the "facts" about that subject. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fluree is based on an extended version of the W3C standard for RDF, which is where this notion of SPO (Subject, Predicate, Object) comes from.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can think of it like a row in a db table with &lt;code&gt;_id&lt;/code&gt; being the unique identifier for the row, predicates are the columns, and the values are the fields. Each field makes up a fact about the instance of data stored in that particular row in the db. For example, in a Dog table with a Breed column, each row corresponds to a unique Dog who is described by the attributes and fields. The same idea holds in Fluree. An &lt;code&gt;_id&lt;/code&gt; groups the related predicates, which point to values, in order to make up the "facts" of that subject. So, the &lt;code&gt;dog/breed&lt;/code&gt; predicate would point at an object, &lt;code&gt;"french bulldog"&lt;/code&gt;, for example. At the point in time when that fact was written to the ledger, that specific subject's breed was french bulldog.&lt;/p&gt;

&lt;p&gt;Each of these facts are stored in an immutable data structure. Immutable means that those data structures are not available to be modified or changed in any way. Instead of simply changing a value or updating a "row" in the data, Fluree will make a new true fact in the ledger and associate it with the appropriate subject. If this is a value which is being "modified" then Fluree will make two new facts; one where the old fact is false and the second a new, true fact, both of these facts are then associated with the subject and written to the ledger. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is part of the "extension" to RDF. Each flake contains a boolean which indicates whether it is true or has been falsified. You can read more about this in the &lt;a href="https://docs.flur.ee/guides/1.0.0/architecture/flakes#flakes-as-flurees-foundation" rel="noopener noreferrer"&gt;flakes page&lt;/a&gt; in the docs. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This brings us to what a ledger is. You can think of a ledger as discrete units or "blocks" which contain the history of the data as it is transacted. These blocks are made of groups of immutable facts which are sent to an instance of Fluree. Each block is linked to the one which came before it so there is a chain of blocks from when the ledger was created to the current block. In Fluree, this chain is queryable, which means once some data has been transacted to Fluree you have the history of every data element in that data set! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flvza8gu4gaxg4yqjqgzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flvza8gu4gaxg4yqjqgzv.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Time travel
&lt;/h2&gt;

&lt;p&gt;So, back to those powerful pieces of functionality I mentioned at the beginning. &lt;br&gt;
There are two ways of querying the data which enable what we call time travel in the Fluree world. There are &lt;strong&gt;block&lt;/strong&gt; queries and &lt;strong&gt;history&lt;/strong&gt; queries, both unlock elements of Fluree which are only possible because of the immutable data structures and the ledger. Block queries enable querying the data state at specific moments in time and history queries allow you to get an overview of all of the modifications to a particular subject. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4j7xii41jbe9eftjdxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4j7xii41jbe9eftjdxz.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;We'll get into how each of these types of queries work, but first, why does this even matter? &lt;br&gt;
One of the primary benefits to having this type of view into your data is the ability to correlate events with the data state at the time that event happened. For example, say you are tracking prices for flights and you want to see what effect the weather had on flight prices or which day of the week prices tended to be the cheapest. The sky's the limit for these types of analytical queries. &lt;br&gt;
You also may want to enable your users to see the state of some piece of data when it was updated. I saw a comment on a LinkedIn post once and was pretty sure that the commenter worked for the company who's post he was commenting on, but his current job title was recently updated so I couldn't tell where he worked when the comment was added, only where he currently worked - the current state of the data. &lt;br&gt;
This type of functionality can be useful in a wide range of circumstances or situations. Having a way to view not only the current state of the data (table stakes for any database), but a way to see the state of a piece of data at a specified time OR for a specified range of time, can be extremely useful. Fluree goes a step further though. When you are querying some data a point in time, you are also seeing all of the facts which were true at that time as well. This includes all of the relationships which existed at the time. This is something which is not possible in any other database or data store that I am aware of. You are able to query not only the historical values of something in your data but also all of the context associated with that data as well. &lt;strong&gt;That is huge&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Now, think about how you would go about making something like this in your db of choice. Building out a historical view of a table in a traditional database, whether in a relational or NoSQL db, is a large and expensive maintenance burden, the size of your db will explode because of data duplication without significant optimization, and querying these db tables or documents can become relatively complex; specifically what happens to references? Does the reference point to the current table or is there a way to manage the reference such that it points to the correct row in the historical table? What happens when you want to do a join to with another table? There isn't an expedient or simple way to do either of those things, to my knowledge. One or two other data stores enable historical views, but are not able to pull in all of the context and maintain relationships as well. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8ldfla5sl21ij0ewhvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8ldfla5sl21ij0ewhvu.png" alt="Lying_down_working"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;Both of these operations are exposed via an API within a Fluree db instance. Simply passing a JSON to the &lt;code&gt;/block&lt;/code&gt; or &lt;code&gt;/history&lt;/code&gt; endpoint is all that is needed to query this type of data. Let's get into how to use each of these queries. I will be using the Fluree Query Language (FlureeQL), which is a JSON-based way to query the backend. Fluree also supports querying via GraphQL, SPARQL, SQL or calling these endpoints directly from Clojure, but we'll use FlureeQL to illustrate this functionality. If you want to read more about our query surfaces, check out the &lt;a href="https://docs.flur.ee/docs/1.0.0/query/overview" rel="noopener noreferrer"&gt;query pages&lt;/a&gt; for more details. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u8bamzn25oik6lsg95v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u8bamzn25oik6lsg95v.png" alt="Blocks"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Block Queries
&lt;/h3&gt;

&lt;p&gt;There are two ways to query a block in Fluree. You can either issue a query against the &lt;code&gt;/block&lt;/code&gt; endpoint which returns the flakes in that particular block or range of blocks, or you can add a &lt;code&gt;"block"&lt;/code&gt; key to a basic query issued to the &lt;code&gt;/query&lt;/code&gt; endpoint. This basic query method of querying can, and probably will, pull in facts which were transacted to the ledger before the specified block. When you issue a regular query with a block key, you are issuing a query as if the specified block were the current block. &lt;br&gt;
Each of these types of query is beneficial, and can be useful depending on how you need to view your data. &lt;/p&gt;

&lt;p&gt;Let's start with a query issued to the &lt;code&gt;/block&lt;/code&gt; endpoint. This type of query currently supports 2 keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;number,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prettyPrint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;boolean&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;"prettyPrint"&lt;/code&gt; is a boolean, which if true, prints the results in a pretty printed, aka styled format, for easier reading, as well as separating the asserted and retracted flakes into their own arrays in order to make them easier to parse. The &lt;code&gt;"block"&lt;/code&gt; key is much more interesting. It can take a number, a string in the form of an ISO-8601 formatted date-time or duration, or an array which specifies a range of block for the query. &lt;/p&gt;

&lt;p&gt;For example, to query a specific block:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can query via a time stamp. This will return the first block which was transacted before this timestamp. In other words, it will give you the facts which were true at that time.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2017-11-14T20:59:36.097Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also use an &lt;a href="https://en.wikipedia.org/wiki/ISO_8601#Durations" rel="noopener noreferrer"&gt;ISO-8601 formatted duration&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PT5M"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will return the state of the data as of 5 minutes ago. &lt;/p&gt;

&lt;p&gt;If you would like to query a range of blocks, you can pass an array containing the blocks you would like to see. This range is inclusive, meaning the data returned will &lt;em&gt;include&lt;/em&gt; both blocks you put in the array.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also pass an array with a single block which will specify a lower, also inclusive, block and return the facts from that block up to the current block. &lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;/block&lt;/code&gt; endpoint will return an array of &lt;a href="https://docs.flur.ee/guides/1.0.0/architecture/flakes#flakes-as-flurees-foundation" rel="noopener noreferrer"&gt;flakes&lt;/a&gt;, each of which is a fact stored in Fluree at that block or range of blocks. While this is useful, it is probably more realistic that you would want to see a specific set of data using a normal query, but have the results returned as if they had been issued at some point in the past. This is also enabled in Fluree by issuing a query to the &lt;code&gt;/query&lt;/code&gt; endpoint which contains the &lt;code&gt;"block"&lt;/code&gt; key-value pair. This key expects the value to be structured in the same way as the examples above, with the value being one of a number, a formatted string, or an array of block numbers. So the main difference is that this type of query will pull in data which is not limited to a specific block, it returns data as if the query had been issued when that block was the current block. For example, if you had a Dog collection of subjects in your ledger, you could issue this query to see all of the dogs which had been transacted and not deleted as of block 7:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"select"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To read more on querying blocks, check out the docs pages for &lt;a href="https://docs.flur.ee/docs/1.0.0/query/block-query" rel="noopener noreferrer"&gt;block queries&lt;/a&gt; and &lt;a href="https://docs.flur.ee/docs/1.0.0/query/overview#block-key" rel="noopener noreferrer"&gt;querying with the block key&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c4o4hf2n0mia8hdogtr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c4o4hf2n0mia8hdogtr.png" alt="Brain Graphic"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  History Queries
&lt;/h3&gt;

&lt;p&gt;The way a &lt;code&gt;/history&lt;/code&gt; query is structured and issued is relatively similar to &lt;code&gt;/block&lt;/code&gt; queries, but are fairly different in what results are returned. As I mentioned above, a history query returns all of the modifications to a subject. I like to think of a block query showing the breadth of the data at a specific time and the history query as looking down the timeline of a specific piece of data.&lt;br&gt;
For example, if you had a customer in your dataset who has connections to other customers, you could see the history of that customer's connections from when they first joined your application up to the current block. If you wanted to see the connections that customer had at a specific block or over a range of blocks, that is possible, as is using the ISO-8601 date-times or durations.&lt;br&gt;&lt;br&gt;
You can build a &lt;code&gt;/history&lt;/code&gt; query using FlureeQL in JSON the same way you would with a &lt;code&gt;/block&lt;/code&gt; query. For example, if you know the subject's &lt;code&gt;_id&lt;/code&gt; you can simply hit the &lt;code&gt;/history&lt;/code&gt; endpoint like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"history"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;351843720888320&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This query will return an array of objects, each object containing the block and t numbers for that block and an array of flakes for that subject.&lt;br&gt;&lt;br&gt;
Another option is to issue a history query with a block key in order to constrain the results of the query to a specific timeframe in your data. That looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"history"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;369435906932737&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This query will return the flakes for this &lt;code&gt;_id&lt;/code&gt; up to block 4. You can also use a block range or use the ISO-8601 formatted string similar to the &lt;code&gt;/block&lt;/code&gt; queries. &lt;/p&gt;

&lt;p&gt;Using a flake format is another way you can  issue a history query. This means that you can use pieces of data to identify the subject you want to query. This works via the subject, predicate, object structure of a flake. You pass the elements you want to use to query in an array as the value of the "history" key in the query JSON. The array needs to be passed as &lt;code&gt;["subject", "predicate", "object"]&lt;/code&gt;, but you do not have to use all 3 elements in the array for the query to resolve.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that the order of these within the array is important and either a subject or a predicate is required. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, if you want to query for the history of all subjects matching the predicate object pair &lt;code&gt;dog/breed&lt;/code&gt; &lt;code&gt;"french bulldog"&lt;/code&gt; in your collection, you could query the ledger like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"history"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"dog/breed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"french bulldog"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Another way this could be done is using either a subject &lt;code&gt;_id&lt;/code&gt; with a predicate, or substitute a two-tuple which uniquely identifies a subject for the &lt;code&gt;_id&lt;/code&gt;.&lt;br&gt;
That would look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"history"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="mi"&gt;351843720888320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"dog/favFoods"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;or with a two-tuple&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"history"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dog/name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jacques"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"dog/favFoods"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Both of these queries will return the history of the predicate &lt;code&gt;"dog/favFoods"&lt;/code&gt; for the dog specified, with either the subject &lt;code&gt;_id&lt;/code&gt; or the unique identifier of &lt;code&gt;["dog/name" "Jacques"]&lt;/code&gt; used to identify the subject you want to inspect. &lt;br&gt;
Similar to the &lt;code&gt;"/block"&lt;/code&gt; queries, a &lt;code&gt;"/history"&lt;/code&gt; query can also accept a &lt;code&gt;"prettyPrint"&lt;/code&gt; key-value pair. When true this will return the history of the subject or predicate as indicated, but will separate out the retracted and asserted flakes per block into their own arrays. That looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"history"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;351843720888320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prettyPrint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;which will return something in this type of structure:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"asserted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;351843720888320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"dog/breed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"french bulldog"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"retracted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the return JSON, each block containing data which matches the query is its own labeled object containing a named array for asserted and retracted.&lt;/p&gt;
&lt;h3&gt;
  
  
  "showAuth"
&lt;/h3&gt;

&lt;p&gt;There is one other extremely powerful way to use &lt;code&gt;"/history"&lt;/code&gt; queries to audit the history of who transacted the data. You can issue a &lt;code&gt;"showAuth"&lt;/code&gt; boolean key-value pair or an array of &lt;code&gt;_auth/id&lt;/code&gt; or &lt;code&gt;_auth&lt;/code&gt; subject &lt;code&gt;_id&lt;/code&gt;'s in order to filter the history query to specific auth record's transactions. Because each transaction is signed by a private key which is associated cryptographically with the &lt;code&gt;_auth/id&lt;/code&gt;, every flake in Fluree contains a record of who issued that transaction. This is the way to view that data. It looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"history"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;351843720888320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"showAuth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will return an array of block objects, each of which will contain a named array of &lt;code&gt;"auth"&lt;/code&gt; which consists of the auth's subject &lt;code&gt;_id&lt;/code&gt; and the &lt;code&gt;"_auth/id&lt;/code&gt; of the individual (man or machine) which signed that block. Which will look something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"flakes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17592186044436&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17592186044437&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17592186044438&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ferret"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"t"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="mi"&gt;105553116266496&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"TexTgp1zpMkxJq1nThrgwkU5dp9wzaXA7BX"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For more information on how Fluree stores and interacts with identity and authorization, please take a look at the &lt;a href="https://docs.flur.ee/guides/1.0.0/identity/auth-records" rel="noopener noreferrer"&gt;identity section&lt;/a&gt; in the docs. &lt;/p&gt;
&lt;h2&gt;
  
  
  Wrap it up
&lt;/h2&gt;

&lt;p&gt;So that's how you can go about time traveling in Fluree. There are powerful tools which come out-of-the box which enable you to do things like query as of a specific moment in time, see how a subject evolved over time in your dataset, or get all of the data which was transacted by a specific auth record. You can read more about it in our &lt;a href="//docs.flur.ee"&gt;docs site&lt;/a&gt; or if you would prefer to engage with our community, come join us on &lt;a href="https://launchpass.com/flureedb" rel="noopener noreferrer"&gt;Slack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more detail about this subject, you can watch our Time and Immutability Webinar on YouTube: &lt;iframe width="710" height="399" src="https://www.youtube.com/embed/CLZm3ZjvQqM"&gt;
&lt;/iframe&gt;
&lt;br&gt;
This has video has a publicly available demo  which you can review here: &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fluree" rel="noopener noreferrer"&gt;
        fluree
      &lt;/a&gt; / &lt;a href="https://github.com/fluree/time-webinar" rel="noopener noreferrer"&gt;
        time-webinar
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demo app which uses the create-react-app template for Fluree to embed a webworker with the application. This demo showcases functionality around issuing block and history queries.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Time and Immutability Webinar Demo&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;This is the repository used for the demo in the &lt;a href="https://www.youtube.com/watch?v=CLZm3ZjvQqM&amp;amp;t=1972s" rel="nofollow noopener noreferrer"&gt;Time and Immutability Webinar&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Set up&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;To begin working with this demo app, you will need to have Fluree running locally on your machine
For detailed instruction on getting Fluree installed, please visit the &lt;a href="https://docs.flur.ee/docs/1.0.0/getting-started/installation" rel="nofollow noopener noreferrer"&gt;installation page on the docs site&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You will also need to have &lt;a href="https://nodejs.org/en/download/" rel="nofollow noopener noreferrer"&gt;Node.js&lt;/a&gt; installed on your machine.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/fluree/time-webinar/tree/main/data" rel="noopener noreferrer"&gt;data folder&lt;/a&gt; contains the seed data for using this application as it is shown in the webinar.
To get the data loaded into your Fluree instance, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the Admin UI and create a ledger called time/webinar.&lt;/li&gt;
&lt;li&gt;Using either the Admin UI or a REST client of your choosing (Postman, Insomnia, etc.) transact the files in the data/ folder, in order, to your ledger
&lt;ul&gt;
&lt;li&gt;This will transact the schema&lt;/li&gt;
&lt;li&gt;The airports and tags for the statuses&lt;/li&gt;
&lt;li&gt;The flight.json files…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fluree/time-webinar" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>database</category>
      <category>blockchain</category>
      <category>immutability</category>
      <category>fluree</category>
    </item>
    <item>
      <title>Tutorial: To-Do List Generator V2: Identity and Permissions</title>
      <dc:creator>Flor Marshall</dc:creator>
      <pubDate>Mon, 21 Jun 2021 18:06:30 +0000</pubDate>
      <link>https://dev.to/fluree/tutorial-to-do-list-generator-v2-identity-and-permissions-n3k</link>
      <guid>https://dev.to/fluree/tutorial-to-do-list-generator-v2-identity-and-permissions-n3k</guid>
      <description>&lt;h2&gt;
  
  
  Issuing &lt;strong&gt;Identity and Permissions&lt;/strong&gt; at the Data layer with Fluree DB
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;This tutorial is a follow up to the first tutorial found &lt;a href="https://dev.to/fluree/tutorial-build-a-to-do-list-generator-with-fluree-38co"&gt;here&lt;/a&gt; on dev.to or on &lt;a href="https://github.com/fluree/to-do-lists-generator" rel="noopener noreferrer"&gt;github&lt;/a&gt; on the &lt;code&gt;to-do-list&lt;/code&gt; branch, where we built a to-do list generator using React and Fluree. If you are not familiar with Fluree, please refer to the first part of this tutorial series to learn the basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To get started git clone the repo via &lt;code&gt;git clone https://github.com/fluree/version-2-lists-generator.git&lt;/code&gt;, or any other preferred method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into the repo and run &lt;code&gt;npm install&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;then run &lt;code&gt;npm start&lt;/code&gt; to locally serve the app in your browser at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Fluree
&lt;/h2&gt;

&lt;p&gt;As previously mentioned Fluree is a Web3-capable graph database platform powered by an &lt;a href="https://docs.flur.ee/guides/1.0.0/intro/what-is-fluree" rel="noopener noreferrer"&gt;immutable ledger&lt;/a&gt;. The &lt;a href="https://docs.flur.ee/guides/1.0.0/architecture" rel="noopener noreferrer"&gt;architecture&lt;/a&gt; of Fluree gives developers a lot of freedom and control over the way data is managed, specifically the enabling of permissions that go along with data maintenance. Unlike regular dbs, plagued with data-silos and ever changing APIs to manage application-specific permissions and identity, Fluree offers the ability to implement them directly in the data layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Identity and Permissions
&lt;/h2&gt;

&lt;p&gt;To fully understand the way identity and permissions work in Fluree, we will need to dive into the different collections and predicates that help facilitate this capability.&lt;/p&gt;

&lt;h3&gt;
  
  
  User, Auth, Rules, and Roles
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;_user&lt;/code&gt;, &lt;code&gt;_auth&lt;/code&gt;, &lt;code&gt;_rule&lt;/code&gt;, and &lt;code&gt;_role&lt;/code&gt; are built in collections within Fluree that hold the criteria needed to implement user permissions and control identity. Below is a diagram showcasing how each collection is connected to each other by their predicates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfktwpwmjpn60f292mwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfktwpwmjpn60f292mwr.png" alt="relationship-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A user can have an auth record associated with their identity, that auth record is then governed by the roles associated with it. Each specific role has rules that dictate their access (read and write) to the data. The role that comes straight out of the box in Fluree is &lt;code&gt;["_role/id","root"]&lt;/code&gt;, this role has full read and write access to the db. Users can have multiple roles connected to their auth record, and each role can have a different set of rules as well. Also users can have multiple auth records, but multiple users cannot share the same auth record.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is worth noting that an auth record does not need to be tied to a user, they can be used independently with a collection of your choosing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Generating Auth records with Public-Private Keys
&lt;/h3&gt;

&lt;p&gt;The way auth records control identity in Fluree are by tying the record to a specific public-private key pair (specifically generated using the &lt;a href="https://docs.flur.ee/guides/1.0.0/architecture/blockchain#proving-identity" rel="noopener noreferrer"&gt;secp256k1 elliptic curve&lt;/a&gt;). This cryptographic identity enables the user to sign their transactions and queries according to their permissions. There are a number of ways to generate the public-private key/auth id triple, and can be found &lt;a href="https://docs.flur.ee/guides/1.0.0/identity/auth-records#generating-a-public-private-keyauth-id-triple" rel="noopener noreferrer"&gt;here&lt;/a&gt; in the docs. In this tutorial we will be issuing them using the Admin UI in the sections below.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Signing queries and transactions can be done in different ways found &lt;a href="https://docs.flur.ee/guides/1.0.0/identity/signatures" rel="noopener noreferrer"&gt;here&lt;/a&gt;, in this tutorial we use the &lt;code&gt;@fluree/crypto-utils&lt;/code&gt; library.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Integrating identity and permissions into the Application
&lt;/h2&gt;

&lt;p&gt;Now that we have a basic understanding of how identity and permissions can be used within Fluree lets take these concepts and configure them within our application. We will need to refine our schema, add roles and rules, create smart functions, and generate auth records with private-public keys.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure to change the network and db variables located in the &lt;code&gt;appConfig.js&lt;/code&gt; to mirror your Fluree network and db namespace, and double-check that you're using the correct port (e.g. :8090).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Schema Changes
&lt;/h3&gt;

&lt;p&gt;In the previous version of this application the &lt;code&gt;_user&lt;/code&gt; collection was not used, but now that we need to leverage permissioning we will utilize the &lt;code&gt;_user&lt;/code&gt; collection, along with their &lt;code&gt;username&lt;/code&gt; predicate. The only other additions are the following predicates: &lt;code&gt;list/listOwner&lt;/code&gt;, &lt;code&gt;assignee/user&lt;/code&gt;, and &lt;code&gt;task/issuedBy&lt;/code&gt;, where all of these predicates reference the &lt;code&gt;_user&lt;/code&gt; collection. The &lt;code&gt;list/listOwner&lt;/code&gt; predicate references a single user, while the&lt;code&gt;assignee/user&lt;/code&gt; predicate is &lt;code&gt;multi: true&lt;/code&gt;, meaning it can reference multiple users, given that a list can have more than one assignee. The entire schema can be found &lt;a href="https://github.com/fluree/version-2-lists-generator/blob/to-do-V2-auth_and_permissions/src/data/01-Schema.json" rel="noopener noreferrer"&gt;here&lt;/a&gt;and transacted to a new Fluree ledger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Roles and Rules
&lt;/h3&gt;

&lt;p&gt;We have two types of users: list-owners and assignees. In this scenario we do not need to create multiple roles for these users, one role is suitable to control what the different users can see and do. Any difference in how list-owners and assignees can interact with lists and tasks can be permissioned based on how each user is linked to those records in the schema.&lt;/p&gt;

&lt;p&gt;We will create an &lt;strong&gt;endUser&lt;/strong&gt; role and utilize the existing &lt;strong&gt;root&lt;/strong&gt; role.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvy0s6xubls5eqo01gnuo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvy0s6xubls5eqo01gnuo.png" alt="two-roles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can transact our new role to the DB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_role?endUser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"endUser"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the root role and our additional endUser role we need to create the rules that will govern what the roles can and cannot do. Below is a graphic with the rules associated with each role.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfv3e8r3jpzzo3j8m85y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfv3e8r3jpzzo3j8m85y.png" alt="rules-for-each-role"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first glance it doesn't seem like the root user and the endUser differ in what they can and cannot do, but in order to fully grasp how the rules are enforced we need to dive into &lt;a href="https://docs.flur.ee/guides/1.0.0/smart-functions/smart-functions" rel="noopener noreferrer"&gt;Smart Functions&lt;/a&gt;. Smart functions are functions written in Clojure*, they can be triggered with any query or transaction that a user attached to a certain role issues. These smart functions live in the &lt;code&gt;_fn&lt;/code&gt; collection, the &lt;code&gt;_rule&lt;/code&gt; collection has a predicate called &lt;code&gt;_rule/fns&lt;/code&gt; which is a reference to this collection. So when an action takes place the smart function that is connected to a certain rule is evaluated and will either return &lt;strong&gt;true&lt;/strong&gt; or &lt;strong&gt;false&lt;/strong&gt; depending if the user in question has the permission to execute the desired action.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;*Currently, Smart Functions are only usable in Clojure, although we are alpha-testing a version of Fluree that allows for JavaScript-written Smart Functions as well. Stay tuned for updates!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Rules and Smart Functions
&lt;/h3&gt;

&lt;p&gt;It is important to note that smart functions are not limited to use in rules, they can be used in &lt;code&gt;_collection/spec&lt;/code&gt;, &lt;code&gt;_predicate/spec&lt;/code&gt;, &lt;code&gt;_predicate/txSpec&lt;/code&gt; and even in transactions, an example of each can be found &lt;a href="https://docs.flur.ee/guides/1.0.0/smart-functions/smart-functions" rel="noopener noreferrer"&gt;here&lt;/a&gt;. But for the purpose of demonstrating permissions, all of our smart functions are connected to the rules mentioned above. Now lets create a rule that is connected to a smart function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_rule$fullAccessOwnListData"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fullAccessOwnListData"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A _user with this rule can only view and edit their own list data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"_fn$fullAccessOwnListData"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ops"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"all"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"collection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"predicates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_fn$fullAccessOwnListData"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fullAccessOwnListData?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A _user can query and edit their own list data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(relationship? (?sid) [&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;list/listOwner&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;_user/auth&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;] (?auth_id))"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON snippet above is an example of a transaction that issues both a &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/identity#_rule" rel="noopener noreferrer"&gt;&lt;code&gt;rule&lt;/code&gt;&lt;/a&gt; and its accompanying &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/functions" rel="noopener noreferrer"&gt;&lt;code&gt;fn&lt;/code&gt;&lt;/a&gt;. Starting with the rule object it includes a temporary id (for the transaction) that will evaluate to a integer once it's in Fluree. It also includes an &lt;code&gt;id&lt;/code&gt;, a &lt;code&gt;description&lt;/code&gt;, the &lt;code&gt;fns&lt;/code&gt; associated with the rule in the form of a temporary id, &lt;code&gt;ops&lt;/code&gt; is set to &lt;code&gt;all&lt;/code&gt; (meaning this applies to both actions: transact and query), and the collection and its predicates to which this rule is attributed to. In this case it applies to the &lt;code&gt;list&lt;/code&gt; collection and all of its predicates.&lt;/p&gt;

&lt;p&gt;In short, this rule indicates that the &lt;code&gt;fullAccessOwnListData&lt;/code&gt; smart function will be run every time a user with this rule either transacts or queries any data field available to records in the &lt;code&gt;list&lt;/code&gt; collection.&lt;/p&gt;

&lt;p&gt;The next object is a transaction item that creates the smart function connected to this rule. It uses a temporary id, a name, a description, and the code is in Clojure. Clojure is a Lisp family language developed for the Java Virtual Machine, and is the language Fluree uses to program its core software. For an in-depth look at Clojure's syntax visit &lt;a href="https://learnxinyminutes.com/docs/clojure/" rel="noopener noreferrer"&gt;Learn X in Y minutes: Clojure&lt;/a&gt;, and useful introduction material can be found at &lt;a href="https://www.braveclojure.com/clojure-for-the-brave-and-true/" rel="noopener noreferrer"&gt;Clojure for the Brave and True&lt;/a&gt;. Lets break the code down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;relationship?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;?sid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sc"&gt;\"&lt;/span&gt;&lt;span class="n"&gt;list/listOwner&lt;/span&gt;&lt;span class="sc"&gt;\"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;\"&lt;/span&gt;&lt;span class="n"&gt;_user/auth&lt;/span&gt;&lt;span class="sc"&gt;\"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;?auth_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/functions#universal-functions-for-_fncode" rel="noopener noreferrer"&gt;subset of Clojure functions&lt;/a&gt; that can be used in the code, but in this tutorial all of our smart functions use the &lt;code&gt;relationship?&lt;/code&gt; function. The syntax for the &lt;code&gt;relationship?&lt;/code&gt; function is as follows &lt;code&gt;(function startSubject path endSubject)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In our implementation, this maps to the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;function&lt;/code&gt;: &lt;code&gt;relationship?&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;startSubject&lt;/code&gt;: &lt;code&gt;(?sid)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;(?sid)&lt;/code&gt; is a &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/functions#context-dependent-functions" rel="noopener noreferrer"&gt;context-dependent function&lt;/a&gt; which refers to the specific subject id being queried/transacted in the context of the current function evaluation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;path&lt;/code&gt;: &lt;code&gt;[\"list/listOwner\" \"_user/auth\"]&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;path&lt;/code&gt; can be a single predicate or a vector of predicates that potentially connect the two subjects. Essentially, for the &lt;code&gt;relationship?&lt;/code&gt; smart function to be satisfied, we use this schema-defined path to evaluate whether a relationship exists between two subjects. In our example, if the data links a list to the user accessing the list, via the path of &lt;code&gt;list/listOwner&lt;/code&gt;, then we can understand the user accessing the list is the owner and should be entitled to specific permissions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;endSubject&lt;/code&gt;: &lt;code&gt;(?auth_id)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;(?auth_id)&lt;/code&gt; is also a context-dependent function and refers to the specific auth record (i.e. public cryptographic identity) that is querying/transacting against the data at the time of the smart function evaluation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The whole code evaluates if the relationship between the subject id and the auth record id return true, given the path. In this example in order for a &lt;code&gt;listOwner&lt;/code&gt; to view their list data, their id must have a connection to the auth record id, via the path &lt;code&gt;[list/listOwner _user/auth]&lt;/code&gt; that bridges that connection within the data &amp;amp; the schema that models it.&lt;/p&gt;

&lt;p&gt;Not all rules may need a custom smart function as the one above, in some cases a user's ability to query and transact certain data should always be true. That means there does not have to be a startSubject or endSubject evaluated through a path. For a rule to always evaluate to true we simply set the &lt;code&gt;_rule/fns&lt;/code&gt; to &lt;code&gt;"fns": [[ "_fn/name","true"]]&lt;/code&gt;, the same can be done if a rule must always evaluate to false.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_rule$canViewAssignees"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"canViewAssignees"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A _user with this rule can view all assignee data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"_fn/name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ops"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"collection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"predicates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The transaction above is a rule where all users can view assignee data, so this rule will always evaluate to true.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We won't go over every rule and their smart functions connected to the endUser role, however they can all be found &lt;a href="https://github.com/fluree/version-2-lists-generator/blob/to-do-V2-auth_and_permissions/src/data/03-rules.json" rel="noopener noreferrer"&gt;here&lt;/a&gt; and transacted to the Fluree ledger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auth records and public-private keys
&lt;/h3&gt;

&lt;p&gt;Now that the roles and rules are transacted into the ledger it is time we create auth records for our users and connect them to public-private keys in order for us to sign queries and transaction, as well as see it in the app UI.&lt;/p&gt;

&lt;p&gt;The sample schema provided &lt;a href="https://github.com/fluree/version-2-lists-generator/blob/to-do-V2-auth_and_permissions/src/data/04-Sample-data.json" rel="noopener noreferrer"&gt;here&lt;/a&gt; has users with nested auth records, like the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_user$6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rootUser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tf3VDot4jSKHFcLY8HSPsuf2yA5YBnRsEPU"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"roles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"_role/id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This auth id is already tied to a public-private key pair, in the sense that it is &lt;a href="https://docs.flur.ee/guides/1.0.0/identity/auth-records#generating-a-public-private-keyauth-id-triple" rel="noopener noreferrer"&gt;derived directly from an secp256k1 public key&lt;/a&gt;. This auth record just needs to be transacted, along with the rest of the sample data. The gif below shows how to generate an auth record with private-public keys through the admin UI, by selecting &lt;em&gt;transact&lt;/em&gt; on the left navigation bar, then pressing the &lt;em&gt;Generate Keys&lt;/em&gt; button above the code editor.&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvideos.files.wordpress.com%2FzObXZely%2Fgenerate_pub_priv_keys_mp4_hd.mp4" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvideos.files.wordpress.com%2FzObXZely%2Fgenerate_pub_priv_keys_mp4_hd.mp4" alt="generating public private keys"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This will prompt a modal to appear with the &lt;strong&gt;Public Key&lt;/strong&gt;, &lt;strong&gt;Private Key&lt;/strong&gt;, and &lt;strong&gt;Auth Id&lt;/strong&gt;. You can either transact the auth record within the modal (remembering to make the appropriate role changes if necessary), then connect the auth id to a user in a separate transaction, or you can copy the auth object, and nest it into a user transaction similar to the one above. &lt;strong&gt;But be sure to save the public and private keys externally before closing the modal&lt;/strong&gt;. In this tutorial there have six users in our sample data and their public-private keys and auth ids are kept in the &lt;a href="https://github.com/fluree/version-2-lists-generator/blob/to-do-V2-auth_and_permissions/src/data/usersAuth.js" rel="noopener noreferrer"&gt;usersAuth.js&lt;/a&gt;. Once the sample data is fully transacted, we can now move on to issuing signed queries and transactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signing Queries and Transactions
&lt;/h2&gt;

&lt;p&gt;The marriage between issuing permissions and generating private-public keys takes place when users sign queries and transactions. The signature proves that whoever is issuing the query or transaction has access to the private key, and so on successful submission it validates their access to view the data or make changes. There are a few ways to go about signing, in this tutorial we use the NPM package, &lt;a href="https://github.com/fluree/crypto-utils" rel="noopener noreferrer"&gt;&lt;code&gt;@fluree/crypto-utils&lt;/code&gt;&lt;/a&gt;, but other methods can be found &lt;a href="https://docs.flur.ee/guides/1.0.0/identity/signatures" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signing Queries
&lt;/h3&gt;

&lt;p&gt;The query below uses the &lt;code&gt;signQuery&lt;/code&gt; function. It takes a private key, param, queryType, host, and db as parameters (defined below), then it returns an object with keys: &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;method&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt;, which can be sent to the &lt;code&gt;/query&lt;/code&gt; endpoint (or other possible endpoints such as &lt;code&gt;/multi-query&lt;/code&gt;, &lt;code&gt;history&lt;/code&gt;, and &lt;code&gt;block&lt;/code&gt;). This specific query can be found &lt;a href="https://github.com/fluree/version-2-lists-generator/blob/48c54ed2dd21b20c098d56aa53c3854a44760a54/src/ListContext.js#L138" rel="noopener noreferrer"&gt;here&lt;/a&gt;, it is triggered on load and defaults to the rootUser on the tab component. Each tab option is a different user with different permissions. The lists view changes given their identity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@fluree/crypto-utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;usersAuth&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/usersAuth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchListData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;assignedTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ASC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectedUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchListData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;signed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/query`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//fetch issues the request to the given url and takes the output of signedQuery.&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setLists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/not found/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;this didn't work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Signing Transactions
&lt;/h3&gt;

&lt;p&gt;These are two example transactions, they both use the &lt;code&gt;signTransaction&lt;/code&gt; function, which takes an auth id, db, expire, fuel, private key, tx, and optional deps. It is similar to the query version, but the output of &lt;code&gt;signTransaction&lt;/code&gt; is then placed within the body of the POST request. Please refer to &lt;a href="https://github.com/fluree/version-2-lists-generator/blob/bb0497f7bfa988764b6b9573ec4ff954ad858050/src/ListContext.js#L260" rel="noopener noreferrer"&gt;deleteTaskFromFluree&lt;/a&gt; and &lt;a href="https://github.com/fluree/version-2-lists-generator/blob/bb0497f7bfa988764b6b9573ec4ff954ad858050/src/ListContext.js#L334" rel="noopener noreferrer"&gt;editTaskProps&lt;/a&gt; for their full implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signTranaction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@fluree/crypto-utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;usersAuth&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/usersAuth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;deleteTaskFromFluree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectedUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectedUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expire&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fuel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chosenTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;_action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;signedCommandOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;fuel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;tx&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchOpts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedCommandOne&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;command`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchOpts&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;editTaskProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectedUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectedUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expire&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fuel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskChangeTransact&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;signedCommandTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;fuel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;tx&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchOpts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedCommandTwo&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;command`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchOpts&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrap up
&lt;/h3&gt;

&lt;p&gt;At its core identity and permissions within Fluree are simply data, but with security in the data layer power and scalability are not at the mercy of firewalls and APIs. It's time to move away from application-centricity and embrace data-centricity.&lt;/p&gt;

&lt;p&gt;To learn more about architecture, infrastructure, and identity, visit the Fluree &lt;a href="https://docs.flur.ee/guides/1.0.0/intro/intro" rel="noopener noreferrer"&gt;guides&lt;/a&gt; section. And for other repo examples visit our &lt;a href="https://github.com/fluree/developer-hub" rel="noopener noreferrer"&gt;developer hub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>database</category>
      <category>security</category>
      <category>blockchain</category>
      <category>fluree</category>
    </item>
    <item>
      <title>Tutorial: Build a To-Do List Generator With Fluree</title>
      <dc:creator>Flor Marshall</dc:creator>
      <pubDate>Thu, 29 Apr 2021 15:05:11 +0000</pubDate>
      <link>https://dev.to/fluree/tutorial-build-a-to-do-list-generator-with-fluree-38co</link>
      <guid>https://dev.to/fluree/tutorial-build-a-to-do-list-generator-with-fluree-38co</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e3itlhemia3qlisuca6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e3itlhemia3qlisuca6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This tutorial is designed to introduce a simple React application that utilizes &lt;a href="https://flur.ee/" rel="noopener noreferrer"&gt;FlureeDB&lt;/a&gt; to manage data. A basic understanding of React is assumed, as is basic experience with a relational DB and querying/inserting data with SQL. &lt;/p&gt;

&lt;p&gt;We will break down the different technologies that make up Fluree, and show how data lives and is connected within Fluree. Then demonstrate how to integrate it in an application, by using any HTTP client (in this application we use &lt;a href="https://axios-http.com/" rel="noopener noreferrer"&gt;axios&lt;/a&gt;), queries and transactions are issued to create, read, update, and destroy data from the FlureeDB. &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To get started git clone the &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/to-do-list/README.md" rel="noopener noreferrer"&gt;repo&lt;/a&gt; via &lt;code&gt;git clone https://github.com/fluree/to-do-lists-generator.git&lt;/code&gt;, or any other preferred method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into the repo and run &lt;code&gt;npm install&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;then run &lt;code&gt;npm start&lt;/code&gt; to locally serve the app in your browser at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;React&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To keep things simple this application uses Create React App.&lt;/p&gt;

&lt;p&gt;You can learn more in the &lt;a href="https://facebook.github.io/create-react-app/docs/getting-started" rel="noopener noreferrer"&gt;Create React App documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To learn React, check out the &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;What is Fluree?&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://flur.ee/" rel="noopener noreferrer"&gt;Fluree&lt;/a&gt; is a Web3-capable graph database platform powered by an &lt;a href="https://docs.flur.ee/guides/1.0.0/intro/what-is-fluree" rel="noopener noreferrer"&gt;immutable ledger&lt;/a&gt; backplane.&lt;/p&gt;

&lt;p&gt;If you are not familiar with chain or blockchain data, think of it as a list of provable transactions that are sequenced by time. This ledger is tamper-proof and each block in the ledger is linked to the previous block.&lt;/p&gt;

&lt;p&gt;Every block contains critical metadata like a hash, a timestamp, and the size of the block data (block-bytes). The core data that constitutes each block, though, are extensions of RDF triples that we call &lt;a href="https://docs.flur.ee/guides/1.0.0/intro/what-is-fluree#flakes" rel="noopener noreferrer"&gt;flakes&lt;/a&gt;. These flakes contain all the data that is added, updated, or deleted at the moment in time described by each block. Flakes are an integral part of Fluree and are used to represent everything: for a in-depth look at Flakes refer to the &lt;a href="https://docs.flur.ee/guides/1.0.0/architecture/flakes" rel="noopener noreferrer"&gt;architecture&lt;/a&gt; docs.&lt;/p&gt;

&lt;p&gt;Fluree's graph schemas are made up of &lt;a href="https://docs.flur.ee/guides/1.0.0/intro/what-is-fluree#collections-and-predicates" rel="noopener noreferrer"&gt;collections and predicates&lt;/a&gt;, we will go further into how to use them in the Schema section below.&lt;/p&gt;

&lt;p&gt;At its core, data in Fluree leverages the &lt;a href="https://www.w3.org/TR/rdf-concepts/" rel="noopener noreferrer"&gt;Resource Description Framework (RDF)&lt;/a&gt;. RDF is a W3C standard model for data interchange on the Web*. Data in Fluree is modelled by the &lt;a href="https://www.w3.org/TR/rdf-concepts/#section-triples" rel="noopener noreferrer"&gt;RDF Triple&lt;/a&gt;, which contains a subject, a predicate, and an object.&lt;/p&gt;

&lt;p&gt;A simple example would be: "The sky's color is blue", where 'sky' is the subject, 'color' is the predicate, and 'blue' is the object. When comparing the same sentence to the typical approach of an entity–attribute–value model: entity(sky), attribute(color), value(blue).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;*For a more in-depth look into RDF refer to the W3C &lt;a href="https://www.w3.org/RDF/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Getting Started with Fluree&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This to-do list app uses &lt;a href="https://docs.flur.ee/docs/1.0.0/getting-started/fluree-anywhere" rel="noopener noreferrer"&gt;Fluree Anywhere&lt;/a&gt; to manage data, for a in-depth installation guide of Fluree visit the &lt;a href="https://docs.flur.ee/docs/1.0.0/getting-started/installation" rel="noopener noreferrer"&gt;Installation&lt;/a&gt; docs. For brief installation points refer below.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Installing Fluree&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://s3.amazonaws.com/fluree-releases-public/fluree-stable.zip" rel="noopener noreferrer"&gt;Download&lt;/a&gt; latest stable version and unzip Fluree (fluree-1.0-latest)&lt;/li&gt;
&lt;li&gt;Launch Fluree with default options by running &lt;code&gt;./fluree_start.sh&lt;/code&gt; in the terminal for Macs and in Bash emulator for Windows.&lt;/li&gt;
&lt;li&gt;Once Fluree is done starting up it will be available for use behind port 8090, e.g. &lt;code&gt;http://localhost:8090&lt;/code&gt;. [Note: for versions below 1.0.0 the default web server port may be :8080]. Navigating to :8090 in your browser will serve Fluree's default AdminUI. The Fluree server behind :8090 will also respond to POST requests against Fluree's HTTP API endpoints.&lt;/li&gt;
&lt;li&gt;To exit, click &lt;code&gt;ctrl + c&lt;/code&gt; to kill the thread in your terminal. This will not delete any ledgers or successful transactions.&lt;/li&gt;
&lt;li&gt;For further installation information visit the &lt;a href="https://docs.flur.ee/docs/1.0.0/getting-started/installation" rel="noopener noreferrer"&gt;Installation&lt;/a&gt; docs.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Fluree requires Java 11 or above. To verify your version run &lt;code&gt;java --version&lt;/code&gt; in the terminal or visit &lt;a href="https://www.java.com/en/download/manual.jsp" rel="noopener noreferrer"&gt;java&lt;/a&gt; to download.&lt;/p&gt;

&lt;p&gt;For those who use Docker: &lt;code&gt;docker run -p 8090:8090 -v $PWD/data:/var/lib/fluree fluree/ledger&lt;/code&gt; (no installation or other dependencies necessary). Refer to Fluree Docker installation &lt;a href="https://docs.flur.ee/docs/1.0.0/getting-started/installation#fluree-with-docker" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating your Ledger, Schema, and Sample Data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this section we will break down ledger creation, implementing a basic schema, and adding sample data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Ledger&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A ledger in Fluree is basically the mechanism which stores and keeps track of &lt;a href="https://docs.flur.ee/docs/1.0.0/transact/updating-data" rel="noopener noreferrer"&gt;&lt;em&gt;updates&lt;/em&gt;&lt;/a&gt; or &lt;a href="https://docs.flur.ee/docs/1.0.0/transact/basics" rel="noopener noreferrer"&gt;&lt;em&gt;transactions&lt;/em&gt;&lt;/a&gt; to your data. There are a few different ways to create a new ledger, for more details refer to the &lt;a href="https://docs.flur.ee/docs/1.0.0/getting-started/ledger-operations" rel="noopener noreferrer"&gt;ledger&lt;/a&gt; docs.&lt;/p&gt;

&lt;p&gt;Here we will create a new ledger in the admin UI:&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8yp8pmxyvdvjt2karkm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8yp8pmxyvdvjt2karkm5.png" alt="Fluree admin UI"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;After pressing the 'Add Ledger' button you will see the modal below. Enter a network name and DB name, for example: &lt;code&gt;test/one1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepck39cag6rm759hayw8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepck39cag6rm759hayw8.png" alt="Ledger Modal"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The name of your network and ledger will become part of the unique URL that includes the API endpoint. Example: &lt;code&gt;http://localhost:8090/fdb/test/one1/query&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Schema&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once the ledger has been created the next step is to build your schema. Schemas in Fluree consist of &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/collections" rel="noopener noreferrer"&gt;&lt;em&gt;collections&lt;/em&gt;&lt;/a&gt; and &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/predicates" rel="noopener noreferrer"&gt;&lt;em&gt;predicates&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can think of &lt;em&gt;collections&lt;/em&gt; as tables in a relational DB and &lt;em&gt;predicates&lt;/em&gt; as columns, although you should refer to the &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/overview" rel="noopener noreferrer"&gt;Schema&lt;/a&gt; section in the docs for a more elaborate explanation. An important detail to note is that Schemas in Fluree are just data, and the easiest way to add data is using our JSON syntax to represent the schema and transact it into the database. As you see below, we are using this JSON syntax -- aka FlureeQL -- to create our transactions. FlureeQL combines features from GraphQL and SPARQL while maintaining a convenient JSON shape.&lt;/p&gt;

&lt;p&gt;Below is the schema for the to-do list generator:&lt;/p&gt;

&lt;p&gt;The schema has three collections: &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;task&lt;/code&gt;, and &lt;code&gt;assignee&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_collection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Subjects in this collection will be individual to-do lists, which can reference several specific tasks."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_collection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Subjects in this collection will be individual tasks, which can reference individual assignees"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_collection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Subjects in this collection describe individuals who could be assigned specific tasks"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;We've added some &lt;code&gt;doc&lt;/code&gt; strings to each collection and predicate to offer additional clarity for users. This descriptive metadata does not affect the schema other than to aid any developers who need to understand it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each collection has three predicates.&lt;/p&gt;

&lt;p&gt;The list collection consists of list/name, list/description, and list/tasks&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list/name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The name of the list. This is indexed for easier querying, but is not a unique value from one list to another"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list/description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A string describing the list"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list/tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ref"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"multi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"restrictCollection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Because one list can include multiple tasks, this allows a single list subject to make graph references to multiple task subjects"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The task collection consists of task/name, task/assignedTo, and task/isCompleted&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task/name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The name of the task"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task/assignedTo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ref"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"restrictCollection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A ref between a task and an assignee, modeling the individual to whom the task is assigned"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task/isCompleted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The completion status of the task"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The assignee collection consists of assignee/name, assignee/email, and assignee/lists&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee/name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The name of the assignee"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee/email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"unique"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The email of the assignee"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_predicate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee/lists"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ref"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"multi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"restrictCollection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The lists owned by an individual -- this is potentially different from the tasks that are assigned to a specific individual"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;An important thing to note about predicates is that within Fluree they are their own type of collection, so they can consist of predicates themselves (you can think of them as properties that describe a type of predicate). For example, &lt;code&gt;_predicate/name&lt;/code&gt; is a predicate that belongs to the &lt;code&gt;_predicate&lt;/code&gt; collection. For a list of types and further explanation refer to the &lt;a href="https://docs.flur.ee/docs/1.0.0/schema/predicates#_predicate-predicates" rel="noopener noreferrer"&gt;predicate&lt;/a&gt; docs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you have solidified your schema you can insert it into your DB, using the admin UI, as your first transaction:&lt;/p&gt;


&lt;p&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3pk5ycitfz7wmbl59z1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3pk5ycitfz7wmbl59z1.gif" alt="transacting schema"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the example gif above we transacted only the collection schema as a separate transaction item, but if we wanted to transact the schema (collection and predicates) together, we can easily achieve this by creating a single transaction array with each transaction item as individual objects. Refer to the example &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/to-do-list/src/data/Schema" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To explore your schema and understand the connectedness of each collection and predicates, Fluree gives you the ability to visualize each relationship. In the gif below we select &lt;em&gt;Schema&lt;/em&gt; on the left nav bar then press the &lt;em&gt;Launch Schema Explorer&lt;/em&gt; button.&lt;/p&gt;


&lt;p&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2u1mzhu9yy5cksxttckb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2u1mzhu9yy5cksxttckb.gif" alt="exploring the Schema"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Sample Data&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After setting your schema it is time to transact some data. Similar to how you transacted your schema you will transact data within the admin UI. To grab a copy of the sample data refer to the code &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/to-do-list/src/data/Seed-data" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
 &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb2ciq3qumcibige13ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb2ciq3qumcibige13ys.png" alt="example seed data"&gt;&lt;/a&gt;
 &lt;/p&gt;

&lt;p&gt;When the sample data has been successfully transacted, run the &lt;code&gt;npm start&lt;/code&gt; command to view the application with populated data in the browser (i.e. by opening &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;). You should see the following:&lt;/p&gt;

&lt;p&gt;
 &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5wq2roo6ayqzyfm0h62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5wq2roo6ayqzyfm0h62.png" alt="to do list in browser"&gt;&lt;/a&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Querying and Transacting Data within the application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that you have some data inside of Fluree, we can dive into the way we structure &lt;a href="https://docs.flur.ee/docs/1.0.0/query/overview" rel="noopener noreferrer"&gt;queries&lt;/a&gt; and &lt;a href="https://docs.flur.ee/docs/1.0.0/transact/basics" rel="noopener noreferrer"&gt;transactions&lt;/a&gt; in the application. As this is a simple to do list we will be able to create a new list with 1 or more sets of tasks; each task having an assignee. We are also able to delete a task, and edit a task's name and completion status, and add a new assignee.&lt;/p&gt;

&lt;p&gt;First, lets review the functionality that is connected to the DB and the data that is being received and sent.&lt;/p&gt;

&lt;p&gt;The application will need to pull the &lt;code&gt;assignee&lt;/code&gt; data in order to populate the &lt;code&gt;Select Assignee&lt;/code&gt; dropdown component in the form. We will also need to grab the list data from Fluree when the app initially mounts in order to populate the &lt;code&gt;Todo&lt;/code&gt; and the &lt;code&gt;Task&lt;/code&gt; components. This will all be done by querying Fluree.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While Fluree does allow querying in GraphQL, curl, and SPARQL... queries issued in this application are in FlureeQL's simplified JSON syntax. Please refer to the docs for examples in the &lt;a href="https://docs.flur.ee/docs/1.0.0/query/overview" rel="noopener noreferrer"&gt;languages&lt;/a&gt; mentioned above, by toggling the &lt;em&gt;Display Examples&lt;/em&gt; at the top left corner.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Querying assignee data&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Below is the query that pulls the &lt;code&gt;assignee&lt;/code&gt; data from Fluree when the application loads. You can find it &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/3a9b6d5c47503df9599ae4c50488c50aad40dbe9/src/ListContext.js#L88" rel="noopener noreferrer"&gt;here&lt;/a&gt; within the &lt;code&gt;loadAssignedToData&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"select"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="err"&gt;OR&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="nl"&gt;"select"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee"&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a basic query, where we are selecting all the &lt;code&gt;_id&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;name&lt;/code&gt; predicate values (these can also be substituted with just &lt;code&gt;"*"&lt;/code&gt;) in the assignee collection. This is similar to a SQL query where we would write the same query as,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;    &lt;span class="k"&gt;SELECT&lt;/span&gt;  &lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;OR&lt;/span&gt;

    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refer to the code base &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L88" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the API request that hold the &lt;code&gt;assignee&lt;/code&gt; data query.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Querying list data&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Below is the query that pulls all the related &lt;code&gt;list&lt;/code&gt; data from Fluree when the application loads. You can find it &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/2dc89d3c15b82d943d7226d5af14390ed9f36120/src/ListContext.js#L106" rel="noopener noreferrer"&gt;here&lt;/a&gt; within the &lt;code&gt;fetchListData&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"select"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
            &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
                    &lt;/span&gt;&lt;span class="nl"&gt;"assignedTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; 
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"opts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="nl"&gt;"compact"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can think about this JSON query as "&lt;a href="https://docs.flur.ee/docs/1.0.0/query/advanced-query#crawling-the-graph" rel="noopener noreferrer"&gt;crawling the graph&lt;/a&gt;", wherein we crawl across linked data by representing references from one collection to another as nested objects within our JSON syntax. These references are available through &lt;a href="https://docs.flur.ee/docs/schema/predicates#predicate-types" rel="noopener noreferrer"&gt;ref predicates&lt;/a&gt; such as &lt;code&gt;list/tasks&lt;/code&gt;. So essentially we are selecting ALL the data from the &lt;code&gt;list&lt;/code&gt; collection then each of the records in the &lt;code&gt;task&lt;/code&gt; collection that are specifically linked to each list, since &lt;code&gt;list/tasks&lt;/code&gt; is a reference predicate in the &lt;code&gt;list&lt;/code&gt; collection.&lt;/p&gt;

&lt;p&gt;The next graph-crawl pulls related data from the &lt;code&gt;assignee&lt;/code&gt; collection, since the &lt;code&gt;task/assignedTo&lt;/code&gt; predicate in the &lt;code&gt;task&lt;/code&gt; collection is a reference predicate to the &lt;code&gt;assignee&lt;/code&gt; collection. All the data above is linked via the predefined predicates of type &lt;code&gt;ref&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The other section of this query (below the &lt;code&gt;from&lt;/code&gt; clause), uses the query key of &lt;code&gt;opts&lt;/code&gt; which is not required, but gives you the ability to set optional keys when retrieving data. For a list of optional keys and their descriptions, refer to the doc &lt;a href="https://docs.flur.ee/docs/1.0.0/query/overview#opts-key" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another way of thinking about the predicate type of &lt;code&gt;ref&lt;/code&gt; are as &lt;code&gt;joins&lt;/code&gt; in relational DBs, but the ability to join is a property set to predicates (in Fluree) as displayed in the predicate schema above. A SQL example of the query below would be,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isCompleted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assignedTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;
    &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
    &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;assignee&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assignedTo&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As a schema grows, these sorts of joins can become deeply complicated in a SQL-shaped schema, particularly when joins are mediated by additional join tables. One significant advantage of Fluree's graph schemas and graph query language is the ability to navigate links between data more directly and easily. Another advantage is the ability to query for JSON-shaped data in JSON itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Refer to the code base &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L106" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the API request that hold the &lt;code&gt;list&lt;/code&gt; data query.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Transacting and updating data&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The next set of functionality we will cover are the ones that send transactions to Fluree in the application, these are the equivalent to &lt;code&gt;INSERT&lt;/code&gt; or &lt;code&gt;UPDATE&lt;/code&gt; statements in SQL. When the form component is filled and submitted, the data is sent to Fluree via the &lt;code&gt;/transaction&lt;/code&gt; API. The &lt;code&gt;/transaction&lt;/code&gt; API is also used when a task is deleted, when a task name is edited, or when the checkbox completed status is changed: these are all updates that are sent to Fluree via a transaction.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Transacting data to Fluree&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Here we will break down all the steps that go into transacting the form data to Fluree, and the creation of the transaction that is nested in the API request. Start at the &lt;code&gt;addList&lt;/code&gt; function &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L135" rel="noopener noreferrer"&gt;here&lt;/a&gt; in the code base.&lt;/p&gt;

&lt;p&gt;The const &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L136" rel="noopener noreferrer"&gt;&lt;code&gt;newList&lt;/code&gt;&lt;/a&gt; is the transaction item that holds the list data. Lets run through it and dissect each part, then we will compare it to the seed data we entered earlier. If we were to just transact a list without any linked tasks, it might look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list$1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My List"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is my grocery list"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In FlureeQL's JSON syntax, we differentiate transactions by wrapping each &lt;code&gt;{ transaction object }&lt;/code&gt; in &lt;code&gt;[ bracket notation ]&lt;/code&gt;. This also allows us to imply that a single transaction might &lt;code&gt;[{ include }, { many }, { transaction }, { items }]&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;_id&lt;/code&gt; value must describe the collection this record should belong to. In this example the &lt;code&gt;$1&lt;/code&gt; suffix gives the record a unique "&lt;strong&gt;temporary id&lt;/strong&gt;", in case you need to reference this record elsewhere within your transaction. For more temp id examples visit &lt;strong&gt;Temporary Ids&lt;/strong&gt; in the &lt;a href="https://docs.flur.ee/docs/1.0.0/transact/basics" rel="noopener noreferrer"&gt;Transaction Basics&lt;/a&gt; section of the docs. Below is a diluted example of the query above in SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"list$1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"My List"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"This is my grocery list"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, our lists are most valuable when they link list data to independent task record data. An individual task record transaction might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task$1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Get Milk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"isCompleted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"assignedTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"assignee/email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jDoe@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;When a ref predicate like &lt;code&gt;task/assignedTo&lt;/code&gt; needs to refer to a subject that already exists, Fluree allows you to easily identify that subject by providing a two-tuple of &lt;code&gt;[A_UNIQUE_PREDICATE, THAT_PREDICATE'S_VALUE]&lt;/code&gt;. So that in the example above, we can have this new &lt;code&gt;task&lt;/code&gt; refer to an &lt;code&gt;assignee&lt;/code&gt; whose &lt;code&gt;assignee/email&lt;/code&gt; value is &lt;code&gt;jDoe@gmail.com&lt;/code&gt;. You can also, however, reference a brand new &lt;code&gt;assignee&lt;/code&gt; (see examples below where a new list references a new task), or use a current &lt;code&gt;assignee&lt;/code&gt;'s unique &lt;code&gt;_id&lt;/code&gt; value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Below is an example of the same transaction above in SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isCompleted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assignedTo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'task$1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Get Milk'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;assignee&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'jDoe@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the examples above, we described &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;task&lt;/code&gt; transactions separately, but we can easily transact them at once. Below is an example of the transaction array with nested transaction items that is sent to Fluree on submission of a new list with new tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My List"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is my grocery list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Get Milk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isCompleted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"assignedTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"assignee/email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"fmarshall@flur.ee"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Get Bananas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isCompleted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"assignedTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"assignee/email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"jDoe@gmail.com"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Get Spinach"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isCompleted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"assignedTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"assignee/email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"jDoe@gmail.com"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This could also have been transacted using &lt;strong&gt;Temp IDs&lt;/strong&gt; -- the &lt;code&gt;Seed-data&lt;/code&gt; file in &lt;code&gt;src/data&lt;/code&gt; provides exactly this example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Refer to the code base &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L171" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the API request that holds the &lt;code&gt;list&lt;/code&gt; data transaction.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Adding a new Assignee to Fluree&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Above we presented a transaction with &lt;code&gt;list&lt;/code&gt; data that included an &lt;code&gt;assignee&lt;/code&gt; already within the drop down selection, but there is functionality in place to create a new assignee and send their information to Fluree, before a transaction with all &lt;code&gt;list&lt;/code&gt; data is sent. Below is the query found in &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/e1f3076755e0e669d19d0009488f7ee332b4e8b3/src/ListContext.js#L133" rel="noopener noreferrer"&gt;addNewAssignee&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assignee$1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john.doe@gmail.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same transaction can be mirrored in SQL as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;assignee&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"assignee$1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"john.doe@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refer to the code &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/e1f3076755e0e669d19d0009488f7ee332b4e8b3/src/ListContext.js#L142" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the API request that holds the creation of a new &lt;code&gt;assignee&lt;/code&gt; data transaction.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Updating &amp;amp; Deleting Existing Data in Fluree&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Updating data uses the same structure and syntax as transacting new data to Fluree. We will be updating data by using the &lt;code&gt;_id&lt;/code&gt; retrieved from the query in &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L106" rel="noopener noreferrer"&gt;&lt;code&gt;fetchListData&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Deleting tasks&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L203" rel="noopener noreferrer"&gt;&lt;code&gt;deleteTask&lt;/code&gt;&lt;/a&gt; holds the asynchronous function &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L207" rel="noopener noreferrer"&gt;&lt;code&gt;deleteTaskFromFluree&lt;/code&gt;&lt;/a&gt; that deletes the task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;369435906932736&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delete"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of using temporary ids, here we match the &lt;code&gt;_id&lt;/code&gt; to the intended task then use the &lt;code&gt;_action&lt;/code&gt; transact key to specify a deletion when sent to Fluree. For more on deleting data refer to the &lt;a href="https://docs.flur.ee/docs/1.0.0/transact/deleting-data" rel="noopener noreferrer"&gt;deleting data&lt;/a&gt; section. The same transaction can be written in SQL below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;369435906932736&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refer to the code base &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L207" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the API request that holds the deletion transact item.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Editing tasks&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Similar to the way we delete tasks above, &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L227" rel="noopener noreferrer"&gt;&lt;code&gt;editTasks&lt;/code&gt;&lt;/a&gt; matches the task &lt;code&gt;_id&lt;/code&gt; and includes the data change for the updated name of the task and updated completion status. For more detail updating data refer to the &lt;a href="https://docs.flur.ee/docs/1.0.0/transact/updating-data" rel="noopener noreferrer"&gt;updating data&lt;/a&gt; section. This transaction takes a task that already exists and updates its name and its completion status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;369435906932736&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is my task name now"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"isCompleted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same transaction can be written in SQL as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"This is my task name now"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isCompleted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;369435906932736&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refer to the code base &lt;a href="https://github.com/fluree/to-do-lists-generator/blob/74b1e4ec7554c3d92c558abba359f831ffc5d1c3/src/ListContext.js#L241" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the API request that holds the update transact item.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Learn more&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For other API endpoint and examples visit the Fluree docs, &lt;a href="https://docs.flur.ee/api" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We also have other tutorials, which cover additional Fluree functionality in our &lt;a href="https://github.com/fluree/developer-hub" rel="noopener noreferrer"&gt;Developer Hub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more information on the Fluree ledger and its Blockchain technology visit the &lt;a href="https://docs.flur.ee/guides/1.0.0/architecture/blockchain" rel="noopener noreferrer"&gt;Blockchain&lt;/a&gt; docs.&lt;/p&gt;

&lt;p&gt;A deeper dive into analytical queries and examples visit the docs section, &lt;a href="https://docs.flur.ee/guides/1.0.0/analytical-queries/inner-joins-in-fluree" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A subject we did not cover in this tutorial is &lt;a href="https://docs.flur.ee/guides/1.0.0/smart-functions/smart-functions" rel="noopener noreferrer"&gt;Smart Functions&lt;/a&gt; in Fluree, which can be used in setting permissions to your DB. Here is a full &lt;a href="https://docs.flur.ee/guides/1.0.0/smart-functions/smart-functions" rel="noopener noreferrer"&gt;list&lt;/a&gt; of accepted smart functions.&lt;/p&gt;

</description>
      <category>fluree</category>
      <category>database</category>
      <category>rdf</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
